ぃまだWordPressで消耗してるよっ!

2015年末の状況ですので、今現在は変更されている可能性が多分に含まれます。
VCCW(VirtualBox・Vagrant)・WP-CLI・Wordmove・Gulp などのそれぞれのインストールと基本的な使い方は他のサイトにて確認下さい。
および、内容に未確定な内容を多く含みます。

関連する投稿を実装してみる

2016/03/22 カフーツ ブログJellyVol.49にて公開

簡単にはプラグインを使えば済むハナシではあるが。

ではあるが一方で、自分のブログの様に記事数が少ないとはいえ個別に設定するのも面倒だし1 、出力位置・順序の調整やCSSの修正など、自分の意にそぐわない箇所はどうにかして誤魔化すしか無いのが難点とも言えるけど。
また、関連する投稿を常に表示する必然性を感じなかったので、プラグイン導入より自分で実装した方が早いのではないかと思い実装してみた。
…のだが、どの様なロジックで実装しているのか見えず調べた結果、「その記事のカテゴリ(自分の場合、カテゴリは使用していないのでタグになる)に属する投稿をランダムで選択して表示」というカンジの、知ってしまえば何の事は無いロジックを組めば良いのかと。

当初の目論見では、関連する投稿を表示したいタグとその表示件数を別ファイルで保存(投稿によっては関連する投稿が表示されない場合もあり)という機能は必須として、(実装しなかったが)この投稿はこの投稿へのリンクといったピンポイントの機能も考えていた。
悩んだのは表示したいタグが複数になった場合で、積算か折衷かと考えたけど、積算は関連する投稿が凄く多くなる可能性もあり、折衷はロジックが面倒なので、「どれか一つのタグをランダムに選択する」で落ち着いた。

更に悩んだのは、表示したいタグとその表示件数を別ファイルで保存するのは良いとして、タグ名・スラッグ名・タグIDのいずれで保存するか、だった。
タグ名・スラッグだと後々に変更する可能性もあるのでタグIDが妥当なのだが、これなぁ…タグIDだとそれが何のタグなのか見当が付かないのが難点で。
別ファイルのフォーマットはJSONを考えていたが、JSONにはコメント構文が無いのが難点だけど妥協せざるを得ず…プログラムからは参照しない前提でキーと値のペアを持っていても良かったかもしれない、と思う。

下記はある特定のタグIDに属する投稿の「全件」を取得するロジックで、array_rand() 、つまり配列からランダムに任意のキーを取得、の使い方で微妙に悩んだ。
また、該当するタグの全件取得なので、自分の様なボリュームだと問題無いと思うが、件数によってはパフォーマンスに影響があるかもしれない。

// $my_post_id      : in) その投稿のget_the_ID()
// $display_tag_id  : in) 表示対象のタグID
// $display_post_id : out) 表示する投稿ID配列

$display_post_id_tmp = $display_post_id = array();
$my_query = new WP_Query(array(
    'tag_id' => $display_tag_id,
    'post__not_in' => array($my_post_id),
    'nopaging' => true
  ));
if ($my_query->have_posts()) {
  while ($my_query->have_posts()) {
    $my_query->the_post();
    $display_post_id_tmp[get_the_id()] = null;
  }
}
$display_post_id = array_rand($display_post_id_tmp, $display_tag_count);
wp_reset_postdata();

この後は $display_post_id を回して各種情報を取得するだけなので割愛するとして、この実装で一番手間取ったのは、「どのタグで何件出力するか?」だった。
そもそも自分のあるタグがどの投稿なのか、などの統計的・俯瞰的な情報は持ちあわせてなかったので wp-cli とPHPでさくっと作って確認した後にこの実装を始めた。

まず前提として…

# 記事の一覧
$ wp post list --post_type=post --fields=ID,post_title,post_status,post_date --format=json
# タグの一覧
$ wp term list post_tag --fields=term_id,name,slug,count --format=json

…までは分かっていたが、ある投稿のタグを取得するコマンドが分からず調べた結果、wp post term list を実行すれば良いと。2
ただし、投稿単位でのタグID取得であること、投稿総数によっては時間がかかる。

# 投稿IDが730として「Staticおじさんのひとりごと」「WordPress」「このサイトについて」の3件のタグに関する情報を返している
$ wp post term list 730 post_tag --fields=term_id,name --format=json
[{"term_id":25,"name":"Static\u304a\u3058\u3055\u3093\u306e\u3072\u3068\u308a\u3054\u3068"},{"term_id":6,"name":"WordPress"},{"term_id":9,"name":"\u3053\u306e\u30b5\u30a4\u30c8\u306b\u3064\u3044\u3066"}]

後は wp post list で取得した全記事の投稿IDを回せば取得できるので割愛するとして。
ちょっとハマりそうになったのは、PHPで wp-cli を扱う場合(wp-cli に限らないが)、wp-cli の絶対パス…これはシェルスクリプトやUNIXの問題かと思うが…、wp-cliが参照する Movefile までの絶対パスは明示的に書いておく必要がある。
例えば上記 wp post list の場合だと、下記をPHPで exec() する必要がある。

$ /usr/local/bin/wp --post_type=post --fields=ID,post_title,post_status,post_date --format=json --path=/file/to/path/

…と、とりあずは。
今後、タグと表示件数の微調整が生じると思うが。
また、今回実装しなかった「この投稿はこの投稿へのリンクといったピンポイント」の実装をするかもしれないし、関連する投稿のもう少し詳細なフロントページの様な情報を表示するかもしれないし、といったトコロ。

Menu of this post

  1. 1. だらだらと
  2. 2. WP-CLI・Wordmove
  3. 3. 最もよく見られた投稿をJetpack APIから取得
  4. 4. 関連する投稿を実装してみる
  5. 5. その他の細々とした改修

Footnotes

  1. 1. プラグインによるが、初期状態だと意外と選択された記事の精度が悪い印象がある。

  2. 2. via bash – Add tags/categories to a WordPress post from WP-CLI – Stack Overflow