2009年1月10日の投稿

2009-01-10
くもり

コメントの入れ子に対応

ゆりこ による 00:22:54 の投稿
カテゴリー: WordPressハック,更新履歴
タグ: , ,

コメントが入れ子の画面

当サイトはすでに WordPress 2.7 になっているわけですが、テーマファイルを調整して、コメントの入れ子に対応しました。これによって、各コメントに「返信する」リンクが付くようになりました。「返信する」リンクの直下にコメントフォームが出るという Ajax 化は面倒だったので、コメントフォームは画面最下部のを使うようにしています。

WordPress 2.7 で導入された、コメントの入れ子やページ分割に対応するのは実は簡単で、comments.php のコメントループを wp_list_comments() 関数に入れ替えるだけです。しかし、各コメントのフォーマットは、wp-includes/comment-template.php で定義された Walker_Comment クラスによる画面出力になってしまいます。wp_list_comments() の引数を調整することで、リスト方式を、ol, ul, div から選ぶことはできますが、名前→投稿日時→コメント内容という表示順序は決め打ちになります。これが気に入らなかったので、Walker_Comment を使用中テーマの functions.php にコピーしてクラス名を変更し、中身を改造することにしました。こうすれば出力順序は思いのままです。そして、comments.php では wp_list_comments(array('walker' => new My_Walker_Comment)) のようにすれば、自作クラスを使うことができます。従来の comments.php よりは改造がしにくくなったと言えますが、入れ子を実装するためには Walker クラスが必要なので仕方ないですね。

[追記] よく調べると、Walker_Comment クラスをコピーする必要はありませんでした。Walker_Comment クラスの start_el() メソッドの中身は、コールバック関数を指定して置き換えることが可能になっているからです。つまり、start_el() メソッドの $GLOBALS['comment'] = $comment;
の行以降をテーマの functions.php で定義し、それへのコールバックを wp_list_comments() の callback 引数として与えればよいです。例えば、以下のような感じです。

functions my_list_comments($comment, $args, $depth) {
	$GLOBALS['comment'] = $comment;
	extract($args, EXTR_SKIP);

	if ( 'div' == $args['style'] ) {
		$tag = 'div';
		$add_below = 'comment';
	} else {
		$tag = 'li';
		$add_below = 'div-comment';
	}
?>
	<<?php echo $tag ?> <?php comment_class(empty( $args['has_children'] ) ? 
	'' : 'parent') ?> id="comment-<?php comment_ID() ?>">
	<?php if ( 'ul' == $args['style'] ) : ?>
	<div id="div-comment-<?php comment_ID() ?>">
	<?php endif; ?>
	<div class="comment-author vcard">
	<?php if ($args['avatar_size'] != 0) 
		echo get_avatar( $comment, $args['avatar_size'] ); ?>
	<?php printf(__('<cite class="fn">%s</cite> <span class="says">says:</span>'), 
	get_comment_author_link()) ?>
	</div>
<?php if ($comment->comment_approved == '0') : ?>
	<em><?php _e('Your comment is awaiting moderation.') ?></em>
	<br />
<?php endif; ?>

	<div class="comment-meta commentmetadata"><a href="<?php 
	  echo htmlspecialchars( get_comment_link( $comment->comment_ID ) ) ?>"><?php 
	  printf(__('%1$s at %2$s'), get_comment_date(),  get_comment_time()) ?></a><?php 
	  edit_comment_link(__('(Edit)'),'  ','') ?></div>

	<?php comment_text() ?>

	<div class="reply">
	<?php comment_reply_link(array_merge( $args, 
		array('add_below' => $add_below, 'depth' => $depth, 'max_depth' => $args['max_depth']))) ?>
	</div>
	<?php if ( 'ul' == $args['style'] ) : ?>
	</div>
	<?php endif; ?>
<?php
}

テーマの comments.php では、以下のようにします。

if (function_exists('wp_list_comments')) {
	wp_list_comments(array('callback' => 'my_list_comments'));
} else {
	/* 従来のコメント表示処理 */
}