WordPressの自作プラグインで警告`Illegal offset type in isset or empty`が記録される

表題のように、自作プラグインを有効化して設定画面を設定画面を開いたら、ログに以下のような警告が記録されていました。

PHP Warning: Illegal offset type in isset or empty in /PATH/TO/WORDPRESS/wp-includes/taxonomy.php on line 290

これが設定画面を1度開くごとに4行ずつ増えていく、と。

この警告メッセージは連想配列のキーに「配列」を指定すると発生するとのことです。この時点ではまだ原因は特定できず。

ちなみに、自作プラグインの設定画面では各投稿タイプごとのタクソノミーが階層構造にしているかどうかを判定するようになっています。

<?php
    $postTypes = get_post_types( [], 'objects' );
    foreach ( $postTypes as $postType ) {
        //各投稿タイプに紐付けられているタクソノミーを取得
        $termsObjs = get_object_taxonomies( $postType->name, 'objects' );
        foreach ( $termsObjs as $termsObj ) {
            //階層構造になっているか、`the_posts`の`category`であるかのどちらかならば`if`内の処理を実行
            if( is_taxonomy_hierarchical( $termsObj ) || $termsObj->name === 'category' ) {
?>

<!-- 略 -->

<?php
            }
        }
    }
?>

こんなイメージです。

これに対して、wp-includes/taxonomy.phpの290行目はどうなっているのかというと関数taxonomy_existsで引数を$taxonomyとして、isset( $wp_taxonomies[ $taxonomy ] );でオブジェクトの有無を判定しています。

この関数taxonomy_existsは同ファイルの中でそこそこ使われていて、その中に関数is_taxonomy_hierarchicalがあります。

is_taxonomy_hierarchicalは上述のコードの中で使用していますね。

そこでis_taxonomy_hierarchicalの詳細をCodexで確認します。

引数の$taxonomyタクソノミーオブジェクトの名前、つまり文字列で指定とあります。

……あ、オブジェクトを渡している。ということで以下のように改修。

<?php
    $postTypes = get_post_types( [], 'objects' );
    foreach ( $postTypes as $postType ) {
        //各投稿タイプに紐付けられているタクソノミーを取得
        $termsObjs = get_object_taxonomies( $postType->name, 'objects' );
        $termsObjsNames = get_object_taxonomies( $postType->name, 'names' );
        foreach ( $termsObjs as $termsObj ) {
            //階層構造になっているか、`the_posts`の`category`であるかのどちらかならば`if`内の処理を実行
            if( is_taxonomy_hierarchical( $termsObjsNames ) || $termsObj->name === 'category' ) {
?>

しかし警告は消えず。おかしいな、と思いつつ今度はタクソノミーを取得する関数get_object_taxonomiesを確認します。

上記からは例えば次のような出力が得られます:

Array
(
    [0] => category
    [1] => post_tag
    [2] => post_format
)

何……だと……。

言われてみれば確かにそうですが、第一引数の投稿タイプに紐付いたタクソノミーは複数あるので、名前の一覧……つまり、配列になるわけですね。

これだと、is_taxonomy_hierarchicalに配列が渡ってしまうので警告は変わらず記録されるわけです。

そこで、最終的には以下のようになりました。

<?php
    $postTypes = get_post_types( [], 'objects' );
    foreach ( $postTypes as $postType ) {
        //各投稿タイプに紐付けられているタクソノミーを取得
        $termsObjs = get_object_taxonomies( $postType->name, 'objects' );
        foreach ( $termsObjs as $termsObj ) {
            //階層構造になっているか、`the_posts`の`category`であるかのどちらかならば`if`内の処理を実行
            if( is_taxonomy_hierarchical( $termsObj->name ) || $termsObj->name === 'category' ) {
?>

これで警告は記録されなくなりました。

分かってしまえば何てことはないのですが、少し躓いたのでメモしておきます。

参考

この記事を書いた人

アバター

アルム=バンド

フルスタックエンジニアっぽい何か。LAMPやNodeからWP、gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。