今回の記事は備忘録的なものになるのですが、WordPressのfunctions.phpを編集していて変な挙動に出会ったのでご紹介します。
最初思ったのは、「in_category(子カテゴリ)が、親カテゴリを表示しているときもtrueになってしまう」でした。
結果的には関数の使い方の勘違いだったのですが、エラーにもならず紛らわしかったので書いておきます。
カテゴリーが以下のようになっていました。(もちろん架空の例です)
猫
├── ミケ
├── トラ
└── ハチワレ
で、「表示している記事がトラだったら処理を行いたい」と思って、以下のように実装していました。
$child = get_category_by_slug("tora");
if(in_category($child)){
echo "toraページです!";
}else{
echo "残念ながらあなたが見ているページはtoraページではありません。残念ですね";
}
このとき、ミケカテゴリーやハチワレカテゴリーだけを持っている記事でこの処理を行ったときは、in_category($child)
は無事false
になりました。
もちろん、トラカテゴリーを持っている場合はtrue
になりました。だからうまくいっていると思っていたんです。
しかし、親カテゴリーである「猫」カテゴリーだけ持っている記事でこの処理を行った場合も、true
になっていたというわけです。
in_categoryのドキュメントによると、次のように定義されていました。
in_category( int|string|int|string $category, int|WP_Post $post = null ): bool
オブジェクトを引数にとっていないですね。
一方で、get_category_slugのドキュメントでは次のようでした。
get_category_by_slug( string $slug ): object|false
つまり、オブジェクトを返していますね。
というわけで、get_category_slug
で取得したオブジェクトをそのままin_category
に入れていたから想定した仕様になっていなかったことになります。
具体的には、「in_category(子カテゴリのオブジェクト)
にすると、遡って親カテゴリかどうかも判定してしまう」ということですね。
in_category
にはカテゴリIDを入れればいいので、$child->cat_IDを使えばいいです。
次のように修正すると、意図通りの挙動になります。
$child = get_category_by_slug("tora");
$child_id = $child->cat_ID;
if(in_category($child_id)){
echo "toraページです!";
}else{
echo "残念ながらあなたが見ているページはtoraページではありません。残念ですね";
}
ドキュメントにあたることは本当に大切なことでした。
今回は早いうちに発覚したからよかったのですが、後から発覚したらかなり意味がわからなかったんじゃないかと思います。
いい感じに丸めてくれるのはありがたいものの、時には恐ろしいです…(という感想でよかったのかも若干自信がない)
ちなみに、今回の用途ではis_category
は使えないんですよね。ややこしいよな。