2026年7月11日

2026年7月11日

WordPressのコメントテンプレート(comments.php)をカスタマイズする方法

WordPress のクラシックテーマでは、記事の下のコメント一覧と投稿フォームは comments.php というテンプレートで表示されます。「フォームの見出しや送信ボタンの文言を変えたい」「ウェブサイト(URL)欄を消したい」「独自の入力欄を足したい」といった変更は、comments.php と functions.php で行います。

この記事のコードは、WordPress 6.9.4・PHP 8.3 のクラシックテーマで、コメントの投稿・保存・表示まで確かめています(2026年10月時点)。ブロックテーマ(Twenty Twenty-Five など)ではコメント欄は「コメント」ブロックで組み立てるため、comments.php は使われません。

コメント欄が表示される仕組み

  1. 投稿の個別ページ(single.php など)の中で comments_template() が呼ばれます。
  2. comments_template() は、テーマ(子テーマがあれば子テーマ、無ければ親テーマ)の comments.php を読み込みます。
  3. comments.php の中で、wp_list_comments() がコメント一覧を、comment_form() が投稿フォームを出力します。

テーマに comments.php が無い場合、WordPress は互換用の古いテンプレート(wp-includes/theme-compat/comments.php)で表示します。これは WordPress 3.0 から非推奨で、WP_DEBUG を有効にすると「Please include a comments.php template in your theme.」という非推奨の通知が出ます(検証環境で確認)。コメント欄を持つテーマには comments.php を用意してください。

手順1: 子テーマに comments.php を用意する

配布テーマの comments.php を直接編集すると、テーマの更新で変更が消えます。親テーマの comments.php を子テーマにコピーして、コピーを編集します(子テーマの作り方は「WordPress子テーマの作り方」)。

cd /path/to/wordpress/wp-content/themes
cp parent-theme/comments.php my-child-theme/comments.php

親テーマのファイルは削除しないでください。子テーマに同じ名前のファイルがあれば、そちらが優先されます。

手順2: comments.php の基本の構成

自分で書く場合の基本形です。

<?php
/**
 * コメント欄(comments.php)
 */

// パスワード保護された記事では、パスワード入力前にコメントを出さない。
if ( post_password_required() ) {
	return;
}
?>
<section id="comments" class="comments-area">
	<?php if ( have_comments() ) : ?>
		<h2 class="comments-title">
			<?php
			printf(
				'「%1$s」へのコメント(%2$s件)',
				esc_html( get_the_title() ),
				esc_html( number_format_i18n( get_comments_number() ) )
			);
			?>
		</h2>

		<ol class="comment-list">
			<?php
			wp_list_comments(
				array(
					'style'       => 'ol',
					'short_ping'  => true,
					'avatar_size' => 48,
				)
			);
			?>
		</ol>

		<?php the_comments_navigation(); ?>

		<?php if ( ! comments_open() ) : ?>
			<p class="no-comments">この記事のコメント受付は終了しました。</p>
		<?php endif; ?>
	<?php endif; ?>

	<?php
	comment_form(
		array(
			'title_reply'          => 'コメントを書く',
			'title_reply_to'       => '%s さんに返信する',
			'label_submit'         => 'コメントを送信',
			'comment_notes_before' => '<p class="comment-notes">メールアドレスは公開されません。</p>',
		)
	);
	?>
</section>
部分 役割
post_password_required() パスワード保護された記事で、パスワードが入力されるまでコメント欄を出さない
wp_list_comments() コメント一覧を出力する。style は外側のタグ(ol・ul・div)、avatar_size はアバター画像の大きさ(px)、short_ping はピンバックを1行で出す設定
the_comments_navigation() 「設定 → ディスカッション」でコメントのページ分割を有効にしているときの前後リンク
comment_form() 投稿フォーム。コメントを受け付けていない記事では何も出力しない

style を ol にしたときは、wp_list_comments() を <ol> で囲みます。返信(入れ子)は WordPress が <ol class="children"> で自動的に組み立てます。一覧の HTML をさらに細かく変えたいときは、wp_list_comments() の callback 引数に独自の関数を渡す方法があります(公式リファレンス)。

手順3: フォームの見出しやボタンの文言を変える

手順2のように、comment_form() に配列を渡すと文言を変えられます。よく使う項目は次のとおりです。

キー 変わる場所
title_reply フォームの見出し(初期値は「コメントを残す」)
title_reply_to 返信ボタンを押したときの見出し。%s は返信先の名前に置き換わる
label_submit 送信ボタンの文字
comment_notes_before ログインしていない人向けに、フォームの上に出す説明文
comment_notes_after フォームの下に出す説明文

文言だけなら、テンプレートを書き換えずにこの引数で変えるのが簡単です。

手順4: 「サイト」欄を外し、独自の入力欄を足す

名前・メール・サイトの入力欄は、comment_form_default_fields フィルターで増減できます。次の例は、子テーマの functions.php で「サイト」欄を外し、「所属(任意)」欄を足します。

<?php
/**
 * コメントフォームの「サイト」欄を外し、「所属(任意)」欄を足す。
 */
add_filter( 'comment_form_default_fields', function ( $fields ) {
	unset( $fields['url'] );

	// 「次回のコメントで使用するため…保存する」の欄より前に入れる。
	$cookies = isset( $fields['cookies'] ) ? $fields['cookies'] : '';
	unset( $fields['cookies'] );

	$fields['affiliation'] = '<p class="comment-form-affiliation">'
		. '<label for="affiliation">所属(任意)</label> '
		. '<input id="affiliation" name="affiliation" type="text" value="" size="30" maxlength="100">'
		. '</p>';

	if ( $cookies ) {
		$fields['cookies'] = $cookies;
	}
	return $fields;
} );
  • 配列のキーは author(名前)・email(メール)・url(サイト)・cookies(入力内容を保存するチェックボックス)です。unset( $fields['url'] ) で「サイト」欄が消えます。
  • これらの欄はログインしていない人にだけ表示されます。ログイン中のユーザーには「〜としてログイン中」と表示され、名前・メール欄は出ません。
  • CSS の display:none で隠すだけでは、HTML に欄が残ります。欄そのものを外すには、このフィルターを使います。

フォームから欄を外しても、ボットがフォームを使わずに url の値を直接送ってくると、WordPress はそれをコメントの URL として保存します。URL を一切保存したくない場合は、保存前に呼ばれる preprocess_comment フィルターで空にします(検証環境で、URL を直接送っても空で保存されることを確認)。ログイン中のユーザーのプロフィールの URL も保存されなくなります。

<?php
/**
 * フォームを通さずに送られた URL も保存しない。
 */
add_filter( 'preprocess_comment', function ( $commentdata ) {
	$commentdata['comment_author_url'] = '';
	return $commentdata;
} );

手順5: 追加した欄の値を保存して表示する

フォームに欄を足しただけでは、値は保存されません。コメントが保存された直後に動く comment_post アクションで、コメントメタとして保存します。

<?php
/**
 * 送信された「所属」をコメントメタに保存する。
 */
add_action( 'comment_post', function ( $comment_id ) {
	if ( empty( $_POST['affiliation'] ) ) {
		return;
	}
	$affiliation = sanitize_text_field( wp_unslash( $_POST['affiliation'] ) );
	$affiliation = mb_substr( $affiliation, 0, 100 );
	if ( '' !== $affiliation ) {
		add_comment_meta( $comment_id, 'affiliation', $affiliation, true );
	}
} );

/**
 * コメント本文の前に「所属」を表示する。
 */
add_filter( 'comment_text', function ( $text, $comment = null ) {
	if ( is_admin() || ! $comment instanceof WP_Comment ) {
		return $text;
	}
	$affiliation = get_comment_meta( $comment->comment_ID, 'affiliation', true );
	if ( '' === $affiliation ) {
		return $text;
	}
	return '<p class="comment-affiliation">所属: ' . esc_html( $affiliation ) . '</p>' . $text;
}, 10, 2 );
  • 保存するときは wp_unslash() で WordPress が付けたバックスラッシュを外し、sanitize_text_field() でタグや改行を取り除いています。検証環境で <i>開発部</i> と入力すると、「開発部」だけが保存されました。
  • 表示するときも esc_html() を通します。保存時の処理だけに頼らず、出力のたびにエスケープするのが WordPress の基本です。
  • comment_text フィルターは管理画面のコメント一覧でも使われるため、is_admin() のときは何もしないようにしています。

手順6: 返信(スレッド表示)用のスクリプトを読み込む

「設定 → ディスカッション」でコメントのスレッド(入れ子)表示を有効にしている場合、「返信」をクリックしたときにフォームをそのコメントの下へ移動させるには、WordPress 同梱の comment-reply スクリプトが必要です。テーマが読み込んでいない場合は、子テーマの functions.php に追加します。

<?php
/**
 * スレッド表示(返信)用のスクリプトを読み込む。
 */
add_action( 'wp_enqueue_scripts', function () {
	if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
		wp_enqueue_script( 'comment-reply' );
	}
} );

読み込まれていなくても返信自体はできますが、ページが再読み込みされ、フォームの位置へ移動する動きになります。

うまくいかないとき・運用の注意

症状 確認すること
変更が反映されない 有効なテーマ(子テーマ)の comments.php を編集したか。キャッシュ系プラグインのキャッシュを削除したか。ログイン中だと名前・メール・追加した欄は表示されない
コメント欄が丸ごと出ない 記事の「ディスカッション」でコメントを許可しているか。single.php で comments_template() を呼んでいるか
追加した欄の値が表示されない 承認待ちのコメントではないか。comment_post で保存したメタキー名と、表示側のキー名が同じか
スパムが増えた フォームを変えてもスパム対策にはならない。Akismet などで対策する

スパム対策は「WordPressのコメントスパム対策」、フォームの見た目の調整は「WordPressのコメントフォームをカスタマイズする」も参考にしてください。

まとめ

  • クラシックテーマのコメント欄は comments_template() が読み込む comments.php で表示されます。配布テーマを変えるときは子テーマにコピーして編集します。
  • 見出しやボタンの文言は comment_form() の引数で変えられます。
  • 入力欄の追加・削除は comment_form_default_fields、追加した値の保存は comment_post、表示は comment_text で行い、保存時は sanitize_text_field()、表示時は esc_html() を通します。
  • スレッド表示を使うなら comment-reply スクリプトを読み込みます。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲