WordPress

【WordPress】in_categoryで子カテゴリを指定したとき、親カテゴリ記事でtrueになってしまう?(勘違いでした)

今回の記事は備忘録的なものになるのですが、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は使えないんですよね。ややこしいよな。

Profile

yusukeフリーのwebエンジニア