Let's create! WordPressサイト制作とメンテ/エラー対応から、PHP/CSS/javascriptプログラミング、動画・音・イラスト等制作まで扱うコラム

【WordPressカスタムフィールド検索】meta_queryで、シリアライズ値が入ったフィールドを持つ記事をヒットさせるには?

更新: 2024/02/11 3314文字

meta_queryで、シリアライズ値が入ったフィールドを持つ記事をヒットさせるには

今回は、ちょっと需要があるかもしれない『WordPressカスタムフィールド検索』について取り上げます。 ネットを検索すると『シリアライズ値(a:〇〇:{i:△△;s:◇◇:”〇〇”}みたいな形式)のフィールドが絡むと、検索がめんどくさい』という意見が見受けられますが、この形式のフィールドは絞り込み検索に使えるのでしょうか?さっそく検証していきましょう。

シリアライズ値が入ったフィールドってどんな形式に?(例:_wp_attachment_metadeta)

シリアライズ値が入ったフィールドってどんな形式 このサイトでもちょくちょく取り上げていますが、カスタムフィールドで複数項目が1つのフィールドに入っている場合、このようなシリアライズされた形式になっています。 a:〇〇:{i:△△;s:◇◇:”〇〇”}のような形のフィールド(最初のaは、配列arrayのaと要素数・s:〇〇は文字列型(string)とバイト数)で、一部では検索時にめんどくさいともいわれています。

しかし、このフィールドを取れたりすると、WPカスタムフィールド検索を実装するとき自由度があがるので、『ちょっとやってみるか』となったわけです。

なお、実験には、いつものように・・・ 管理人が作成した、WP著作権フリー曲サイトを使用します(曲作りより開発がメインになってるとか言わないでね笑)。 このサイトでは『ビットレート(1秒間に送受信できるデータ量)』が、128kbps・320kbpsなど複数混在しており、探せたらラクかなと思ったからです。

データベース上では、SQLを使って、わりとサックリヒットさせることができました。この形式のフィールドをWordPressのフロント側から検索してもヒットさせることができると、自由度が一気に上がります。 なお、過去記事(リンク)でもちょっと書いたように、『このフィールドにencoder_options”;s:6:”CBR320″というような記述がある』ので、『CBR128』で、記事をヒットさせてみます

下準備~サブループ検索用ファイルと、テスト用記事を用意し、シリアライズフィールドをコピペ(postを取りたいため)

サブループ検索用ファイルを作って、wp-blog-header.phpを読み込み、フォームを用意する

今回の『シリアライズされたフィールドをもつ記事を取ってみよう』では、通常のメインループではなく、カスタムフィールドを使ったサブループを使うので、『メインループを取るようになっているsearch.php(テーマ組み込み)』のほかに、サブループ検索用ファイル(〇〇search.phpみたいな別名)を用意しました。

そのままではWPの記事を拾わないので『require($_SERVER[‘DOCUMENT_ROOT’] .’/wp-blog-header.php’);』を読み込んで、検索対応できるようにします。 フォームは『input type=”radio” name=”bitrate” value=”128″』のようにし、この値が変数$bitrateに格納されます。最初は一覧を表示させておいて、この変数$bitrate値が入っているときは、別クエリが動くように条件分岐します

postを取りたいため、フィールドをテスト記事にコピペ(_wp_attachment_metadetaは、添付ファイルのメタデータ)

ここで投稿タイプの問題が出てきます。管理人的には『絞り込んで記事(投稿タイプpost)が出るようにしたかった』のですが、『_wp_attachment_metadeta』は、投稿タイプpostのメタデータではなく、添付ファイル (attachment)のメタデータです。そのため、『投稿タイプpostを取るクエリでは出ない』となります。 (*投稿タイプattachmentを取る方法もありますが、長くなるので省きます)

そこでテスト用記事を制作。目的の『CBR128が、フィールド内にあるオーディオデータ』を貼り付けて・・

シリアライズ化してある、_wp_attachment_metadetaの内容を、テストで作ったフィールドにコピペしました。テスト環境はこれでok。あとは、クエリを調整して、このフィールドをもつ記事がヒットするようにします。

シリアライズ値が入ったカスタムフィールドを持つ記事を、検索でヒットさせるコード

コード(はしょっています)

*注:テスト用につき、条件は『CBR128』のものしか書いていません(192などは未実装)。

ポイント~meta_compareの値が『IN』や『=』では、シリアライズされたフィールドを取れない

meta_compareの値が『IN』や『=』では、シリアライズされたフィールドを取れない この手のフィールドの厄介なところは、よく使われる書き方だと出てこないところ。例えば、いろんな値があるからといって、『配列のいずれか含む』という『’value’=> array(‘CBR128′,’128000′),’compare’ => ‘in’』という書き方ではでません。

meta_compareの値が『IN』や『=』では、シリアライズされたフィールドを取れない もちろん、値を持っているとはいえ、完全に一致するわけでもないので『’value’=> ‘CBR128′,’compare’ => ‘=’』(一致)でも出ません。

実行結果~正規表現(’compare’ => ‘REGEXP’)だと取れる

正規表現('compare' => ‘REGEXP’)だと取れる” width=”480″ height=”327″ class=”aligncenter size-full wp-image-7690″ />
上記のgithub gistコードに書いていた、<strong>『’compare’ => ‘REGEXP’』</strong>でやってみた結果です。うまくシリアライズされたフィールド内に『CBR128』の値がある記事をヒットさせることができました。
</p>


<h3><span id=実行結果~〇〇を含む(’compare’ => ‘like’)でも取れる

〇〇を含む('compare' => ‘like’)でも取れる” width=”480″ height=”310″ class=”aligncenter size-full wp-image-7691″ />
〇〇を含む(’compare’ => ‘like’)で行ってみたところ、こちらでも該当の記事を取ることができました。『クエリ実行速度が遅い』といわれるlike・REGEXP検索ですが、単体だとスピードはそんなに気になりません。
ただし、この手のフィールドがいっぱいあったり『’relation’ => ‘OR’』でつないだりすると、<strong>がっつりスピードが落ちる</strong>ので、なるべくこの手のフィールドが少ないように設計できると良いかもです(体験談)。
</p>


<h2><span id=参考リンク(WordPress codex)

あとがき・まとめ

  • WPカスタムフィールドでは、複数項目のフィールドはシリアライズ化されて入っている
  • meta_compareの値が『IN』や『=』では、シリアライズされたフィールドを取れない
  • meta_compareの値が『REGEXP』や『like』だとヒットさせることができる
  • ただし、条件によっては実行速度が一気に落ちるので、見越した設計ができるとベター

まとめるとこんなところでしょうか。今回はかなりシンプルな感じなので、割とサックリ実装できましたが、実際の運用では他の条件もかかわってきます(組み合わせによっては難しい)。シリアライズされたフィールドの取り方も押さえつつ、負荷の少ないクエリで取れるように設計できると、使うユーザーもストレスなく利用できると思うので、いろいろと検討できればと思います。 (うまく検索システム作って、管理人のサイトにも実装します)


【カテゴリ】- WordPressファンクションetc
【タグ】- ,

関連記事