comments.php

I’ll build this as a complete advanced comments.php for your RX theme: safe comments display, custom callback, pagination, comment form, accessibility, spam-safe output, schema-friendly structure, and developer hooks.

Below is a large, advanced, production-ready comments.php for your RX theme. It uses WordPress core functions: wp_list_comments() for listing comments, comment_form() for the comment form, and the_comments_pagination() for comment pagination. These are the correct WordPress template tools for a theme comments file.

Create or replace:

rx-theme/comments.php

with this code:

<?php
/**
 * RX Theme Advanced Comments Template
 *
 * File: comments.php
 *
 * Features:
 * - Safe direct-access protection
 * - Password-protected post support
 * - Custom comment callback
 * - Avatar, author, date, edit link, reply link
 * - Pending moderation notice
 * - Comment pagination top and bottom
 * - Trackback / pingback support
 * - Accessible headings and labels
 * - Advanced comment form fields
 * - Consent checkbox support
 * - Schema-friendly comment markup
 * - Developer-friendly filters and actions
 *
 * @package RX_Theme
 */

defined( 'ABSPATH' ) || exit;

/**
 * Stop loading comments if the post is password protected.
 */
if ( post_password_required() ) {
	return;
}

/**
 * Helper: Get RX comment count text.
 */
if ( ! function_exists( 'rx_theme_comments_title_text' ) ) {
	function rx_theme_comments_title_text() {
		$comment_count = get_comments_number();

		if ( '1' === (string) $comment_count ) {
			return esc_html__( 'One Comment', 'rx-theme' );
		}

		return sprintf(
			esc_html(
				_n(
					'%s Comment',
					'%s Comments',
					$comment_count,
					'rx-theme'
				)
			),
			number_format_i18n( $comment_count )
		);
	}
}

/**
 * Helper: Custom RX comment callback.
 *
 * Used by wp_list_comments().
 */
if ( ! function_exists( 'rx_theme_comment_callback' ) ) {
	function rx_theme_comment_callback( $comment, $args, $depth ) {
		$GLOBALS['comment'] = $comment;

		$comment_id      = get_comment_ID();
		$comment_author  = get_comment_author();
		$comment_type    = get_comment_type();
		$avatar_size     = isset( $args['avatar_size'] ) ? absint( $args['avatar_size'] ) : 64;
		$is_by_post_author = false;

		if ( (int) $comment->user_id > 0 ) {
			$post_author_id = (int) get_post_field( 'post_author', get_the_ID() );
			$is_by_post_author = ( (int) $comment->user_id === $post_author_id );
		}

		$comment_classes = array(
			'rx-comment',
			'rx-comment-type-' . sanitize_html_class( $comment_type ),
		);

		if ( $is_by_post_author ) {
			$comment_classes[] = 'rx-comment-by-post-author';
		}

		?>
		<li <?php comment_class( $comment_classes ); ?> id="comment-<?php echo esc_attr( $comment_id ); ?>" itemprop="comment" itemscope itemtype="https://schema.org/Comment">

			<article id="div-comment-<?php echo esc_attr( $comment_id ); ?>" class="rx-comment-body">

				<header class="rx-comment-header">

					<div class="rx-comment-avatar-wrap">
						<?php
						if ( get_option( 'show_avatars' ) ) {
							echo get_avatar(
								$comment,
								$avatar_size,
								'',
								esc_attr( $comment_author ),
								array(
									'class'         => 'rx-comment-avatar',
									'loading'       => 'lazy',
									'force_display' => false,
								)
							);
						}
						?>
					</div>

					<div class="rx-comment-meta">

						<div class="rx-comment-author-wrap">
							<span class="rx-comment-author" itemprop="author" itemscope itemtype="https://schema.org/Person">
								<span itemprop="name">
									<?php echo esc_html( $comment_author ); ?>
								</span>
							</span>

							<?php if ( $is_by_post_author ) : ?>
								<span class="rx-comment-author-badge">
									<?php esc_html_e( 'Author', 'rx-theme' ); ?>
								</span>
							<?php endif; ?>
						</div>

						<div class="rx-comment-time-wrap">
							<a class="rx-comment-permalink" href="<?php echo esc_url( get_comment_link( $comment ) ); ?>">
								<time
									class="rx-comment-time"
									datetime="<?php comment_time( 'c' ); ?>"
									itemprop="datePublished"
								>
									<?php
									printf(
										esc_html__( '%1$s at %2$s', 'rx-theme' ),
										esc_html( get_comment_date() ),
										esc_html( get_comment_time() )
									);
									?>
								</time>
							</a>
						</div>

					</div>

				</header>

				<?php if ( '0' === (string) $comment->comment_approved ) : ?>
					<div class="rx-comment-awaiting-moderation">
						<?php esc_html_e( 'Your comment is awaiting moderation.', 'rx-theme' ); ?>
					</div>
				<?php endif; ?>

				<div class="rx-comment-content" itemprop="text">
					<?php comment_text(); ?>
				</div>

				<footer class="rx-comment-footer">

					<div class="rx-comment-actions">

						<?php
						comment_reply_link(
							array_merge(
								$args,
								array(
									'add_below' => 'div-comment',
									'depth'     => $depth,
									'max_depth' => $args['max_depth'],
									'before'    => '<span class="rx-comment-reply">',
									'after'     => '</span>',
								)
							)
						);
						?>

						<?php
						edit_comment_link(
							esc_html__( 'Edit', 'rx-theme' ),
							'<span class="rx-comment-edit">',
							'</span>'
						);
						?>

					</div>

				</footer>

			</article>
		<?php
	}
}

/**
 * Helper: Custom pingback / trackback callback.
 */
if ( ! function_exists( 'rx_theme_ping_callback' ) ) {
	function rx_theme_ping_callback( $comment, $args, $depth ) {
		$GLOBALS['comment'] = $comment;
		?>
		<li <?php comment_class( 'rx-ping' ); ?> id="comment-<?php comment_ID(); ?>">
			<div class="rx-ping-body">
				<span class="rx-ping-label">
					<?php esc_html_e( 'Pingback:', 'rx-theme' ); ?>
				</span>

				<?php comment_author_link(); ?>

				<?php
				edit_comment_link(
					esc_html__( 'Edit', 'rx-theme' ),
					'<span class="rx-ping-edit">',
					'</span>'
				);
				?>
			</div>
		<?php
	}
}

$rx_comment_count       = get_comments_number();
$rx_comments_are_open   = comments_open();
$rx_has_comments        = have_comments();
$rx_current_post_id     = get_the_ID();
$rx_comment_order_class = get_option( 'comment_order' ) === 'desc' ? 'rx-comments-newest-first' : 'rx-comments-oldest-first';

?>

<section
	id="comments"
	class="rx-comments-area <?php echo esc_attr( $rx_comment_order_class ); ?>"
	aria-labelledby="rx-comments-title"
>

	<?php do_action( 'rx_theme_before_comments_area' ); ?>

	<?php if ( $rx_has_comments ) : ?>

		<header class="rx-comments-header">

			<h2 id="rx-comments-title" class="rx-comments-title">
				<?php echo esc_html( rx_theme_comments_title_text() ); ?>
			</h2>

			<p class="rx-comments-description">
				<?php
				printf(
					esc_html__( 'Discussion for: %s', 'rx-theme' ),
					'<span>' . esc_html( get_the_title() ) . '</span>'
				);
				?>
			</p>

		</header>

		<?php if ( get_comment_pages_count() > 1 && get_option( 'page_comments' ) ) : ?>
			<nav class="rx-comments-navigation rx-comments-navigation-top" aria-label="<?php esc_attr_e( 'Comments navigation', 'rx-theme' ); ?>">
				<?php
				the_comments_pagination(
					array(
						'prev_text'          => esc_html__( 'Previous Comments', 'rx-theme' ),
						'next_text'          => esc_html__( 'Next Comments', 'rx-theme' ),
						'screen_reader_text' => esc_html__( 'Comments pagination', 'rx-theme' ),
						'aria_label'         => esc_html__( 'Comments pagination', 'rx-theme' ),
						'class'              => 'rx-comments-pagination',
					)
				);
				?>
			</nav>
		<?php endif; ?>

		<div class="rx-comments-list-wrap">

			<ol class="rx-comments-list">
				<?php
				wp_list_comments(
					apply_filters(
						'rx_theme_wp_list_comments_args',
						array(
							'style'             => 'ol',
							'type'              => 'comment',
							'callback'          => 'rx_theme_comment_callback',
							'avatar_size'       => 64,
							'short_ping'        => false,
							'format'            => 'html5',
							'max_depth'         => get_option( 'thread_comments_depth' ),
							'reverse_top_level' => null,
							'reverse_children'  => false,
						)
					)
				);
				?>
			</ol>

		</div>

		<?php
		$rx_pings = get_comments(
			array(
				'post_id' => $rx_current_post_id,
				'type__in' => array( 'pingback', 'trackback' ),
				'status' => 'approve',
			)
		);
		?>

		<?php if ( ! empty( $rx_pings ) ) : ?>
			<section class="rx-pings-area" aria-labelledby="rx-pings-title">
				<h3 id="rx-pings-title" class="rx-pings-title">
					<?php esc_html_e( 'Pingbacks and Trackbacks', 'rx-theme' ); ?>
				</h3>

				<ol class="rx-pings-list">
					<?php
					wp_list_comments(
						array(
							'style'      => 'ol',
							'type'       => 'pings',
							'callback'   => 'rx_theme_ping_callback',
							'short_ping' => true,
							'format'     => 'html5',
						),
						$rx_pings
					);
					?>
				</ol>
			</section>
		<?php endif; ?>

		<?php if ( get_comment_pages_count() > 1 && get_option( 'page_comments' ) ) : ?>
			<nav class="rx-comments-navigation rx-comments-navigation-bottom" aria-label="<?php esc_attr_e( 'Comments navigation', 'rx-theme' ); ?>">
				<?php
				the_comments_pagination(
					array(
						'prev_text'          => esc_html__( 'Previous Comments', 'rx-theme' ),
						'next_text'          => esc_html__( 'Next Comments', 'rx-theme' ),
						'screen_reader_text' => esc_html__( 'Comments pagination', 'rx-theme' ),
						'aria_label'         => esc_html__( 'Comments pagination', 'rx-theme' ),
						'class'              => 'rx-comments-pagination',
					)
				);
				?>
			</nav>
		<?php endif; ?>

	<?php endif; ?>

	<?php if ( ! $rx_comments_are_open && $rx_comment_count && post_type_supports( get_post_type(), 'comments' ) ) : ?>
		<div class="rx-comments-closed">
			<p>
				<?php esc_html_e( 'Comments are closed for this post.', 'rx-theme' ); ?>
			</p>
		</div>
	<?php endif; ?>

	<?php if ( $rx_comments_are_open ) : ?>

		<?php
		$rx_commenter = wp_get_current_commenter();
		$rx_required  = get_option( 'require_name_email' );
		$rx_req_attr  = $rx_required ? ' required="required"' : '';
		$rx_req_mark  = $rx_required ? ' <span class="required">*</span>' : '';

		$rx_fields = array(
			'author' =>
				'<p class="comment-form-author rx-comment-form-field rx-comment-form-author">' .
					'<label for="author">' .
						esc_html__( 'Name', 'rx-theme' ) .
						wp_kses_post( $rx_req_mark ) .
					'</label>' .
					'<input id="author" name="author" type="text" value="' . esc_attr( $rx_commenter['comment_author'] ) . '" size="30" maxlength="245" autocomplete="name"' . $rx_req_attr . ' />' .
				'</p>',

			'email' =>
				'<p class="comment-form-email rx-comment-form-field rx-comment-form-email">' .
					'<label for="email">' .
						esc_html__( 'Email', 'rx-theme' ) .
						wp_kses_post( $rx_req_mark ) .
					'</label>' .
					'<input id="email" name="email" type="email" value="' . esc_attr( $rx_commenter['comment_author_email'] ) . '" size="30" maxlength="100" autocomplete="email" aria-describedby="email-notes"' . $rx_req_attr . ' />' .
				'</p>',

			'url' =>
				'<p class="comment-form-url rx-comment-form-field rx-comment-form-url">' .
					'<label for="url">' .
						esc_html__( 'Website', 'rx-theme' ) .
					'</label>' .
					'<input id="url" name="url" type="url" value="' . esc_attr( $rx_commenter['comment_author_url'] ) . '" size="30" maxlength="200" autocomplete="url" />' .
				'</p>',
		);

		if ( has_action( 'set_comment_cookies', 'wp_set_comment_cookies' ) && get_option( 'show_comments_cookies_opt_in' ) ) {
			$rx_fields['cookies'] =
				'<p class="comment-form-cookies-consent rx-comment-form-field rx-comment-form-cookies">' .
					'<input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes" />' .
					'<label for="wp-comment-cookies-consent">' .
						esc_html__( 'Save my name, email, and website in this browser for the next time I comment.', 'rx-theme' ) .
					'</label>' .
				'</p>';
		}

		$rx_comment_form_args = apply_filters(
			'rx_theme_comment_form_args',
			array(
				'fields'               => $rx_fields,

				'comment_field'        =>
					'<p class="comment-form-comment rx-comment-form-field rx-comment-form-comment">' .
						'<label for="comment">' .
							esc_html__( 'Comment', 'rx-theme' ) .
							' <span class="required">*</span>' .
						'</label>' .
						'<textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525" required="required" aria-required="true" placeholder="' . esc_attr__( 'Write your comment here...', 'rx-theme' ) . '"></textarea>' .
					'</p>',

				'title_reply'          => esc_html__( 'Leave a Comment', 'rx-theme' ),
				'title_reply_to'       => esc_html__( 'Leave a Reply to %s', 'rx-theme' ),
				'cancel_reply_link'    => esc_html__( 'Cancel Reply', 'rx-theme' ),
				'label_submit'         => esc_html__( 'Post Comment', 'rx-theme' ),

				'comment_notes_before' =>
					'<p id="email-notes" class="comment-notes rx-comment-notes">' .
						esc_html__( 'Your email address will not be published. Required fields are marked *', 'rx-theme' ) .
					'</p>',

				'comment_notes_after'  =>
					'<p class="rx-comment-after-notes">' .
						esc_html__( 'Please keep comments respectful, helpful, and related to the article topic.', 'rx-theme' ) .
					'</p>',

				'class_container'      => 'rx-comment-respond comment-respond',
				'class_form'           => 'rx-comment-form comment-form',
				'class_submit'         => 'rx-comment-submit submit',
				'id_form'              => 'rx-commentform',
				'id_submit'            => 'rx-submit-comment',
				'name_submit'          => 'submit',
				'format'               => 'html5',

				'submit_button'        =>
					'<button name="%1$s" type="submit" id="%2$s" class="%3$s">' .
						'%4$s' .
					'</button>',

				'submit_field'         =>
					'<p class="form-submit rx-form-submit">%1$s %2$s</p>',
			)
		);

		comment_form( $rx_comment_form_args );
		?>

	<?php endif; ?>

	<?php do_action( 'rx_theme_after_comments_area' ); ?>

</section>

Also add this in your functions.php so threaded replies work correctly:

/**
 * RX Theme Comment Reply Script
 */
function rx_theme_enqueue_comment_reply_script() {
	if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
		wp_enqueue_script( 'comment-reply' );
	}
}
add_action( 'wp_enqueue_scripts', 'rx_theme_enqueue_comment_reply_script' );

Optional CSS for good design:

/* RX Theme Advanced Comments */
.rx-comments-area {
	margin-top: 48px;
	padding-top: 32px;
	border-top: 1px solid rgba(0, 0, 0, 0.08);
}

.rx-comments-title {
	margin: 0 0 8px;
	font-size: 28px;
	line-height: 1.25;
}

.rx-comments-description {
	margin: 0 0 24px;
	color: #666;
}

.rx-comments-list,
.rx-pings-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.rx-comment {
	margin: 0 0 24px;
}

.rx-comment-body {
	padding: 20px;
	border: 1px solid rgba(0, 0, 0, 0.08);
	border-radius: 12px;
	background: #fff;
}

.rx-comment-header {
	display: flex;
	gap: 14px;
	align-items: flex-start;
	margin-bottom: 14px;
}

.rx-comment-avatar {
	border-radius: 999px;
}

.rx-comment-author {
	font-weight: 700;
}

.rx-comment-author-badge {
	display: inline-block;
	margin-left: 8px;
	padding: 2px 8px;
	border-radius: 999px;
	font-size: 12px;
	font-weight: 700;
	background: #f1f5f9;
	color: #334155;
}

.rx-comment-time-wrap {
	margin-top: 4px;
	font-size: 13px;
	color: #64748b;
}

.rx-comment-permalink {
	color: inherit;
	text-decoration: none;
}

.rx-comment-content {
	margin-top: 12px;
	line-height: 1.75;
}

.rx-comment-content p:last-child {
	margin-bottom: 0;
}

.rx-comment-awaiting-moderation {
	margin: 12px 0;
	padding: 10px 12px;
	border-radius: 8px;
	background: #fff7ed;
	color: #9a3412;
	font-size: 14px;
}

.rx-comment-footer {
	margin-top: 16px;
}

.rx-comment-actions {
	display: flex;
	gap: 12px;
	flex-wrap: wrap;
	font-size: 14px;
}

.rx-comment-actions a {
	text-decoration: none;
	font-weight: 600;
}

.rx-comments-list .children {
	margin: 20px 0 0 32px;
	padding: 0;
	list-style: none;
}

.rx-comments-navigation {
	margin: 24px 0;
}

.rx-comments-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 36px;
	height: 36px;
	margin: 0 3px;
	padding: 0 10px;
	border-radius: 8px;
	text-decoration: none;
	background: #f8fafc;
}

.rx-comments-pagination .page-numbers.current {
	font-weight: 700;
	background: #e2e8f0;
}

.rx-pings-area {
	margin-top: 32px;
}

.rx-ping {
	margin-bottom: 10px;
}

.rx-ping-body {
	padding: 12px 14px;
	border-radius: 8px;
	background: #f8fafc;
}

.rx-comment-respond {
	margin-top: 40px;
}

.rx-comment-form-field {
	margin-bottom: 18px;
}

.rx-comment-form-field label {
	display: block;
	margin-bottom: 6px;
	font-weight: 700;
}

.rx-comment-form input[type="text"],
.rx-comment-form input[type="email"],
.rx-comment-form input[type="url"],
.rx-comment-form textarea {
	width: 100%;
	padding: 12px 14px;
	border: 1px solid rgba(0, 0, 0, 0.14);
	border-radius: 10px;
	font-size: 16px;
}

.rx-comment-form textarea {
	resize: vertical;
}

.rx-comment-submit {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 12px 22px;
	border: 0;
	border-radius: 10px;
	cursor: pointer;
	font-weight: 700;
	background: #111827;
	color: #fff;
}

.rx-comments-closed {
	margin: 24px 0;
	padding: 14px 16px;
	border-radius: 10px;
	background: #f8fafc;
	color: #475569;
}

@media (max-width: 600px) {
	.rx-comment-header {
		gap: 10px;
	}

	.rx-comments-list .children {
		margin-left: 16px;
	}

	.rx-comment-body {
		padding: 16px;
	}
}

This comments.php is safe to use directly in your RX theme and gives you a strong advanced foundation for comment display, replies, moderation message, pagination, pingbacks, and form customization.

Leave a Reply

Your email address will not be published. Required fields are marked *