WordPressでサイト内の全コメントを一覧表示する方法

記事内に商品プロモーションが含まれる場合があります

WordPressテーマSANGOのカスタマイズガイドのコメント数がいつのまにか2500を超えていました。ユーザーの方から「コメントを探しにくい」「投稿ページの下までスクロールするのが大変」などという声をいただいたので、サイト内の全コメント一覧ページを作りました。

プラグインなしでコメント一覧を実装する

はじめに良いプラグインがないか調べてみたのですが、丁度良いものが見つかりませんでした。一覧のデザインまでこだわろうとすると全滅です。というわけで自分でコードを書いて実装することにしました。

ググっても参考になる記事がほとんどなかったので、この投稿では具体的な方法を紹介したいと思います。

大まかな流れ

  1. 固定ページを新規作成し、パーマリンクをcommentsなどにする
  2. テーマのディレクトリ直下にpage-comments.phpというファイルを作成する
  3. page-comments.phpにコメント一覧を表示するためのコードを書く

いろいろなやり方がありますが、今回は最もお手軽な方法を紹介します。

手順1:コメント一覧を載せるページを用意する

まず、コメント一覧をどこに載せるかを考えました。他のテンプレートファイル(single.phppage.phpなど)に依存しないようにしたかったので、専用の固定ページのファイルを作ることにしました。というわけで、まず固定ページを新規作成し、パーマリンクをcommentsにします。

手順2:page-comments.phpを新規作成

今回はcommentsというパーマリンクを設定したので、page-comments.phpというファイルを作成します。これでhttps://example.com/commentsにアクセスしたときにpage-comments.phpが表示されるようになります。

WordPressでは固定ページを表示するときに、パーマリンクに対応する名前のファイル名があるとそれを自動で読み込んでくれます。
固定ページの場合「page-パーマリンク名.php」というファイルが存在していると、page.phpではなく、それを読み込んでくれるのです。

手順3:コードを書く

それではコードを書いていきます。まずは単純にコメント一覧を取得して、全て表示するためのコードを紹介します。

まずはコメント一覧を取得する

page-comments.php
<?php 
  // コメントを取得するための引数
  $get_comments_args = [
    "type"   => "comment",
    "status" => "approve",
  ];
  // コメント一覧を取得して1つずつ出力
  foreach(get_comments($get_comments_args) as $comment) :
?>
  ★ここにコメントを表示する★
<?php endforeach; ?>

コメント一覧はget_comments()で取得できます。引数に配列で「どのコメントを取得するか」という条件を指定します。たとえば

page-comments.php
get_comments(
  [
    "type"   => "comment",
    "status" => "approve",
  ]
)

とすると、コメントを("type"=>"comment")、承認されたものだけ("status"=>"approve")表示するという意味になります。他にも様々な条件を指定できるので公式のリファレンスをチェックしてみてください。
例えば、"parent"=>0を追加することで、コメント一覧から返信を除くことができます。

コメントの内容を出力する

get_comments()によりコメント一覧のオブジェクトが配列で返ってくるので、これをforearchで出力します。例えば、以下のような形。

page-comments.php
<?php 
  foreach(get_comments($get_comments_args) as $comment) :
?>
  <?php echo get_avatar($comment, 50); //投稿者のアイコン(50pxで)?>
  <?php echo $comment->comment_author; //投稿者の名前 ?>
  <?php echo comment_date("Y/m/d", $comment); //投稿日  ?>
  <?php comment_text( $comment->comment_id ); //コメントの本文 ?>
<?php endforeach; ?>

それぞれdivタグやpタグなどでマークアップすれば良いですね(この記事ではスタイリングは省略します)。

ちなみに本文は「$comment->comment_content」でも取得できるのですが、リンクなどのマークアップがすべて失われてしまいます。そこで、comment_text()というWordPressの関数を使います。comment_text( $comment->comment_id )という形でコメントIDを渡せば良い感じに本文を表示してくれます。

ページネーションを実現する

このままだと、1つのページに全てのコメントが出力されてしまいます。サーバーへの負荷、読み込み速度などを考えるとページ分割したいですね。さきほどのコードをページネーションできるように改良します。

page-comments.php
<?php 
  // 1ページあたりのコメント数
  define("COMMENT_NUMBER_PER_PAGE", 15);
  // ページ数をURLパラメータから判定。なければ1ページ目
  $page = (int) @$_REQUEST["page_number"] ?: 1;
  // オフセット(現在のページを基準としたコメント数)
  $offset = ($page * COMMENT_NUMBER_PER_PAGE) - COMMENT_NUMBER_PER_PAGE;
  // コメントを取得するための基本引数
  $comment_base_args = [
    "parent" => 0,
    "type"   => "comment",
    "status" => "approve",
  ];
  // サイト内の合計のコメント数
  $total_comment_count = count(get_comments($comment_base_args));
  // コメントの合計ページ数
  $total_pages = ceil($total_comment_count/COMMENT_NUMBER_PER_PAGE);
  // 各ページのコメントを取得するための引数(さきほどの引数と結合)
  $get_comments_args = array_merge($comment_base_args, [
    "offset" => $offset,
    "number" => COMMENT_NUMBER_PER_PAGE,
  ]);
  // コメントを出力
  foreach(get_comments($get_comments_args) as $comment) :
?>
  ★ここにコメントを表示する★
<?php endforeach; ?>
<?php
  //ページネーション
  echo paginate_links([
    "format"    => "?page_number=%#%",
    "total"     => $total_pages,
    "current"   => $page,
    "prev_text" => "前へ",
    "next_text" => "次へ",
    "type"      => "list"
  ]);
?>

コメント一覧のページネーションをサクッと実現するための関数はWordPressには無いようなので、少し回りくどいコードになっています。以下かんたんな解説です。

URLに「いま何ページ目にいるか」の情報を持たせる

URLパラメータという形でこれを実現します。たとえば2ページ目ならhttps://example.com/comments?page_number=2というURLにします。これで(int) @$_REQUEST["page_number"]というコードでページ数を取得できるようになります。

?page=○というパラメータが理想的なのですが、パーマリンク設定によっては上手く動かない場合があるようです。今回はpage_numberというクドイ表現を選びました。

合計のコメント数やページ数を地道に計算する

サイト内の合計コメント数は、count(get_comments(~))という形で取得しています。コメントの出力時にもget_comments(~)するわけなので、2度関数を読みに行っていて効率が悪いのですが、他にあまり良い方法が思いつきませんでした(こうするしかない?)。
コメントを取得するためのget_comments(~)の引数には「このページでは○番目のコメント(offset)から、いくつ(number)表示するか」という指示も与えてやります。

WordPressでコメント一覧を実現するコード(完成形)

ここまでの内容をまとめると、最終的には以下のようなコードになります。いちおうテーマヘッダーやフッターも含めています。

page-comments.php
<?php get_header(); ?>
<?php 
  define("COMMENT_NUMBER_PER_PAGE", 15);
  $page = (int) @$_REQUEST["page_number"] ?: 1;
  $offset = ($page * COMMENT_NUMBER_PER_PAGE) - COMMENT_NUMBER_PER_PAGE;
  $comment_base_args = [
    "parent" => 0,
    "type"   => "comment",
    "status" => "approve",
  ];
  $total_comment_count = count(get_comments($comment_base_args));
  $total_pages = ceil($total_comment_count/COMMENT_NUMBER_PER_PAGE);
  $get_comments_args = array_merge($comment_base_args, [
    "offset" => $offset,
    "number" => COMMENT_NUMBER_PER_PAGE,
  ]);
?>
<h1>コメント一覧(<?php echo $page; ?>ページ目)</h1>
<div class="comments-list">
  <?php foreach(get_comments($get_comments_args) as $comment) : ?>
    <div class="comment">
      <?php echo get_avatar($comment, 50); ?>
      <?php echo $comment->comment_author; ?>
      <?php echo comment_date("Y/m/d", $comment); ?>
      <?php comment_text( $comment->comment_id ); ?>
    </div>
  <?php endforeach; ?>
</div>
<div class="pagination">
  <?php
    echo paginate_links([
      "format"    => "?page_number=%#%",
      "total"     => $total_pages,
      "current"   => $page,
      "prev_text" => "<i class='fa fa-chevron-left'></i>",
      "next_text" => "<i class='fa fa-chevron-right'></i>",
      "type"      =>  "list"
    ]);
  ?>
</div>
<?php get_footer(); ?>

少し複雑になってしまうので、foreachの中身(コメントの中身)なんかは別のファイルに分けても良いですね。

同じカテゴリーの記事
同じカテゴリーの記事一覧
WordPressの使い方
サルワカ