Outputs a complete commenting form for use within a template.
Most strings and form fields may be controlled through the $args array passed into the function, while you may also choose to use the ‘comment_form_default_fields’ filter to modify the array of default fields if you’d just like to add a new one or remove a single field. All fields are also individually passed through a filter of the ‘comment_form_field_$name’ where $name is the key used in the array of fields.
$argsarrayoptional
fields arrayauthor stringemail stringurl stringcookies stringcomment_field stringmust_log_in stringlogged_in_as stringcomment_notes_before stringcomment_notes_after stringaction string'/wp-comments-post.php'.id_form string'commentform'.id_submit string'submit'.class_container string'comment-respond'.class_form string'comment-form'.class_submit string'submit'.name_submit string'submit'.title_reply string'reply' button label. Default ‘Leave a Reply’.title_reply_to string'reply-to' button label. Default ‘Leave a Reply to %s’, where %s is the author of the comment being replied to.title_reply_before string<h3 id="reply-title" class="comment-reply-title">.title_reply_after string</h3>.cancel_reply_before stringcancel_reply_after stringcancel_reply_link stringlabel_submit string'submit' button label. Default ‘Post a comment’.submit_button string<input name="%1$s" type="submit" id="%2$s" class="%3$s" value="%4$s" />.submit_field string<p class="form-submit">%1$s %2$s</p>, where %1$s is the submit button markup and %2$s is the comment hidden fields.format string'xhtml'. Accepts 'xhtml', 'html5'.Default:array()
$postint|WP_Postoptional
Default:null
function comment_form( $args = array(), $post = null ) {
$post = get_post( $post );
// Exit the function if the post is invalid or comments are closed.
if ( ! $post || ! comments_open( $post ) ) {
/**
* Fires after the comment form if comments are closed.
*
* For backward compatibility, this action also fires if comment_form()
* is called with an invalid post object or ID.
*
* @since 3.0.0
*/
do_action( 'comment_form_comments_closed' );
return;
}
$post_id = $post->ID;
$commenter = wp_get_current_commenter();
$user = wp_get_current_user();
$user_identity = $user->exists() ? $user->display_name : '';
$args = wp_parse_args( $args );
if ( ! isset( $args['format'] ) ) {
$args['format'] = current_theme_supports( 'html5', 'comment-form' ) ? 'html5' : 'xhtml';
}
$req = get_option( 'require_name_email' );
$html5 = 'html5' === $args['format'];
// Define attributes in HTML5 or XHTML syntax.
$required_attribute = ( $html5 ? ' required' : ' required="required"' );
$checked_attribute = ( $html5 ? ' checked' : ' checked="checked"' );
// Identify required fields visually and create a message about the indicator.
$required_indicator = ' ' . wp_required_field_indicator();
$required_text = ' ' . wp_required_field_message();
$fields = array(
'author' => sprintf(
'<p class="comment-form-author">%s %s</p>',
sprintf(
'<label for="author">%s%s</label>',
__( 'Name' ),
( $req ? $required_indicator : '' )
),
sprintf(
'<input id="author" name="author" type="text" value="%s" size="30" maxlength="245" autocomplete="name"%s />',
esc_attr( $commenter['comment_author'] ),
( $req ? $required_attribute : '' )
)
),
'email' => sprintf(
'<p class="comment-form-email">%s %s</p>',
sprintf(
'<label for="email">%s%s</label>',
__( 'Email' ),
( $req ? $required_indicator : '' )
),
sprintf(
'<input id="email" name="email" %s value="%s" size="30" maxlength="100" aria-describedby="email-notes" autocomplete="email"%s />',
( $html5 ? 'type="email"' : 'type="text"' ),
esc_attr( $commenter['comment_author_email'] ),
( $req ? $required_attribute : '' )
)
),
'url' => sprintf(
'<p class="comment-form-url">%s %s</p>',
sprintf(
'<label for="url">%s</label>',
__( 'Website' )
),
sprintf(
'<input id="url" name="url" %s value="%s" size="30" maxlength="200" autocomplete="url" />',
( $html5 ? 'type="url"' : 'type="text"' ),
esc_attr( $commenter['comment_author_url'] )
)
),
);
if ( has_action( 'set_comment_cookies', 'wp_set_comment_cookies' ) && get_option( 'show_comments_cookies_opt_in' ) ) {
$consent = empty( $commenter['comment_author_email'] ) ? '' : $checked_attribute;
$fields['cookies'] = sprintf(
'<p class="comment-form-cookies-consent">%s %s</p>',
sprintf(
'<input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes"%s />',
$consent
),
sprintf(
'<label for="wp-comment-cookies-consent">%s</label>',
__( 'Save my name, email, and website in this browser for the next time I comment.' )
)
);
// Ensure that the passed fields include cookies consent.
if ( isset( $args['fields'] ) && ! isset( $args['fields']['cookies'] ) ) {
$args['fields']['cookies'] = $fields['cookies'];
}
}
/**
* Filters the default comment form fields.
*
* @since 3.0.0
*
* @param string[] $fields Array of the default comment fields.
*/
$fields = apply_filters( 'comment_form_default_fields', $fields );
$defaults = array(
'fields' => $fields,
'comment_field' => sprintf(
'<p class="comment-form-comment">%s %s</p>',
sprintf(
'<label for="comment">%s%s</label>',
_x( 'Comment', 'noun' ),
$required_indicator
),
'<textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525"' . $required_attribute . '></textarea>'
),
'must_log_in' => sprintf(
'<p class="must-log-in">%s</p>',
sprintf(
/* translators: %s: Login URL. */
__( 'You must be <a href="%s">logged in</a> to post a comment.' ),
/** This filter is documented in wp-includes/link-template.php */
wp_login_url( apply_filters( 'the_permalink', get_permalink( $post_id ), $post_id ) )
)
),
'logged_in_as' => sprintf(
'<p class="logged-in-as">%s%s</p>',
sprintf(
/* translators: 1: User name, 2: Edit user link, 3: Logout URL. */
__( 'Logged in as %1$s. <a href="%2$s">Edit your profile</a>. <a href="%3$s">Log out?</a>' ),
$user_identity,
get_edit_user_link(),
/** This filter is documented in wp-includes/link-template.php */
wp_logout_url( apply_filters( 'the_permalink', get_permalink( $post_id ), $post_id ) )
),
$required_text
),
'comment_notes_before' => sprintf(
'<p class="comment-notes">%s%s</p>',
sprintf(
'<span id="email-notes">%s</span>',
__( 'Your email address will not be published.' )
),
$required_text
),
'comment_notes_after' => '',
'action' => site_url( '/wp-comments-post.php' ),
'id_form' => 'commentform',
'id_submit' => 'submit',
'class_container' => 'comment-respond',
'class_form' => 'comment-form',
'class_submit' => 'submit',
'name_submit' => 'submit',
'title_reply' => __( 'Leave a Reply' ),
/* translators: %s: Author of the comment being replied to. */
'title_reply_to' => __( 'Leave a Reply to %s' ),
'title_reply_before' => '<h3 id="reply-title" class="comment-reply-title">',
'title_reply_after' => '</h3>',
'cancel_reply_before' => ' <small>',
'cancel_reply_after' => '</small>',
'cancel_reply_link' => __( 'Cancel reply' ),
'label_submit' => __( 'Post Comment' ),
'submit_button' => '<input name="%1$s" type="submit" id="%2$s" class="%3$s" value="%4$s" />',
'submit_field' => '<p class="form-submit">%1$s %2$s</p>',
'format' => 'xhtml',
);
/**
* Filters the comment form default arguments.
*
* Use 'comment_form_default_fields' to filter the comment fields.
*
* @since 3.0.0
*
* @param array $defaults The default comment form arguments.
*/
$args = wp_parse_args( $args, apply_filters( 'comment_form_defaults', $defaults ) );
// Ensure that the filtered arguments contain all required default values.
$args = array_merge( $defaults, $args );
// Remove `aria-describedby` from the email field if there's no associated description.
if ( isset( $args['fields']['email'] ) && ! str_contains( $args['comment_notes_before'], 'id="email-notes"' ) ) {
$args['fields']['email'] = str_replace(
' aria-describedby="email-notes"',
'',
$args['fields']['email']
);
}
/**
* Fires before the comment form.
*
* @since 3.0.0
*/
do_action( 'comment_form_before' );
?>
<div id="respond" class="<?php echo esc_attr( $args['class_container'] ); ?>">
<?php
echo $args['title_reply_before'];
comment_form_title( $args['title_reply'], $args['title_reply_to'], true, $post_id );
if ( get_option( 'thread_comments' ) ) {
echo $args['cancel_reply_before'];
cancel_comment_reply_link( $args['cancel_reply_link'] );
echo $args['cancel_reply_after'];
}
echo $args['title_reply_after'];
if ( get_option( 'comment_registration' ) && ! is_user_logged_in() ) :
echo $args['must_log_in'];
/**
* Fires after the HTML-formatted 'must log in after' message in the comment form.
*
* @since 3.0.0
*/
do_action( 'comment_form_must_log_in_after' );
else :
printf(
'<form action="%s" method="post" id="%s" class="%s"%s>',
esc_url( $args['action'] ),
esc_attr( $args['id_form'] ),
esc_attr( $args['class_form'] ),
( $html5 ? ' novalidate' : '' )
);
/**
* Fires at the top of the comment form, inside the form tag.
*
* @since 3.0.0
*/
do_action( 'comment_form_top' );
if ( is_user_logged_in() ) :
/**
* Filters the 'logged in' message for the comment form for display.
*
* @since 3.0.0
*
* @param string $args_logged_in The HTML for the 'logged in as [user]' message,
* the Edit profile link, and the Log out link.
* @param array $commenter An array containing the comment author's
* username, email, and URL.
* @param string $user_identity If the commenter is a registered user,
* the display name, blank otherwise.
*/
echo apply_filters( 'comment_form_logged_in', $args['logged_in_as'], $commenter, $user_identity );
/**
* Fires after the is_user_logged_in() check in the comment form.
*
* @since 3.0.0
*
* @param array $commenter An array containing the comment author's
* username, email, and URL.
* @param string $user_identity If the commenter is a registered user,
* the display name, blank otherwise.
*/
do_action( 'comment_form_logged_in_after', $commenter, $user_identity );
else :
echo $args['comment_notes_before'];
endif;
// Prepare an array of all fields, including the textarea.
$comment_fields = array( 'comment' => $args['comment_field'] ) + (array) $args['fields'];
/**
* Filters the comment form fields, including the textarea.
*
* @since 4.4.0
*
* @param array $comment_fields The comment fields.
*/
$comment_fields = apply_filters( 'comment_form_fields', $comment_fields );
// Get an array of field names, excluding the textarea.
$comment_field_keys = array_diff( array_keys( $comment_fields ), array( 'comment' ) );
// Get the first and the last field name, excluding the textarea.
$first_field = reset( $comment_field_keys );
$last_field = end( $comment_field_keys );
foreach ( $comment_fields as $name => $field ) {
if ( 'comment' === $name ) {
/**
* Filters the content of the comment textarea field for display.
*
* @since 3.0.0
*
* @param string $args_comment_field The content of the comment textarea field.
*/
echo apply_filters( 'comment_form_field_comment', $field );
echo $args['comment_notes_after'];
} elseif ( ! is_user_logged_in() ) {
if ( $first_field === $name ) {
/**
* Fires before the comment fields in the comment form, excluding the textarea.
*
* @since 3.0.0
*/
do_action( 'comment_form_before_fields' );
}
/**
* Filters a comment form field for display.
*
* The dynamic portion of the hook name, `$name`, refers to the name
* of the comment form field.
*
* Possible hook names include:
*
* - `comment_form_field_comment`
* - `comment_form_field_author`
* - `comment_form_field_email`
* - `comment_form_field_url`
* - `comment_form_field_cookies`
*
* @since 3.0.0
*
* @param string $field The HTML-formatted output of the comment form field.
*/
echo apply_filters( "comment_form_field_{$name}", $field ) . "\n";
if ( $last_field === $name ) {
/**
* Fires after the comment fields in the comment form, excluding the textarea.
*
* @since 3.0.0
*/
do_action( 'comment_form_after_fields' );
}
}
}
$submit_button = sprintf(
$args['submit_button'],
esc_attr( $args['name_submit'] ),
esc_attr( $args['id_submit'] ),
esc_attr( $args['class_submit'] ),
esc_attr( $args['label_submit'] )
);
/**
* Filters the submit button for the comment form to display.
*
* @since 4.2.0
*
* @param string $submit_button HTML markup for the submit button.
* @param array $args Arguments passed to comment_form().
*/
$submit_button = apply_filters( 'comment_form_submit_button', $submit_button, $args );
$submit_field = sprintf(
$args['submit_field'],
$submit_button,
get_comment_id_fields( $post_id )
);
/**
* Filters the submit field for the comment form to display.
*
* The submit field includes the submit button, hidden fields for the
* comment form, and any wrapper markup.
*
* @since 4.2.0
*
* @param string $submit_field HTML markup for the submit field.
* @param array $args Arguments passed to comment_form().
*/
echo apply_filters( 'comment_form_submit_field', $submit_field, $args );
/**
* Fires at the bottom of the comment form, inside the closing form tag.
*
* @since 1.5.0
*
* @param int $post_id The post ID.
*/
do_action( 'comment_form', $post_id );
echo '</form>';
endif;
?>
</div><!-- #respond -->
<?php
/**
* Fires after the comment form.
*
* @since 3.0.0
*/
do_action( 'comment_form_after' );
}
Fires at the bottom of the comment form, inside the closing form tag.
Fires after the comment form.
Fires after the comment fields in the comment form, excluding the textarea.
Fires before the comment form.
Fires before the comment fields in the comment form, excluding the textarea.
Fires after the comment form if comments are closed.
Filters the comment form default arguments.
Filters the default comment form fields.
Filters the comment form fields, including the textarea.
Filters the content of the comment textarea field for display.
Filters a comment form field for display.
Filters the ‘logged in’ message for the comment form for display.
Fires after the is_user_logged_in() check in the comment form.
Fires after the HTML-formatted ‘must log in after’ message in the comment form.
Filters the submit button for the comment form to display.
Filters the submit field for the comment form to display.
Fires at the top of the comment form, inside the form tag.
Filters the display of the permalink for the current post.
| Version | Description |
|---|---|
| 5.5.0 | Introduced the 'class_container' argument. |
| 4.9.6 | Introduced the 'cookies' default comment field. |
| 4.6.0 | Introduced the 'action' argument. |
| 4.5.0 | The 'author', 'email', and 'url' form fields are limited to 245, 100, and 200 characters, respectively. |
| 4.4.0 | Introduced the 'class_form', 'title_reply_before', 'title_reply_after', 'cancel_reply_before', and 'cancel_reply_after' arguments. |
| 4.2.0 | Introduced the 'submit_button' and 'submit_fields' arguments. |
| 4.1.0 | Introduced the 'class_submit' argument. |
| 3.0.0 | Introduced. |
You must log in before being able to contribute a note or feedback.
© 2003–2024 WordPress Foundation
Licensed under the GNU GPLv2+ License.
https://developer.wordpress.org/reference/functions/comment_form