【WordPressカスタムフィールド検索】meta_queryで、シリアライズ値が入ったフィールドを持つ記事をヒットさせるには?
| 更新: 2024/02/11 | 3314文字
今回は、ちょっと需要があるかもしれない『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』や『=』では、シリアライズされたフィールドを取れない
この手のフィールドの厄介なところは、よく使われる書き方だと出てこないところ。例えば、いろんな値があるからといって、『配列のいずれか含む』という『’value’=> array(‘CBR128′,’128000′),’compare’ => ‘in’』という書き方ではでません。
もちろん、値を持っているとはいえ、完全に一致するわけでもないので『’value’=> ‘CBR128′,’compare’ => ‘=’』(一致)でも出ません。
実行結果~正規表現(’compare’ => ‘REGEXP’)だと取れる
実行結果~〇〇を含む(’compare’ => ‘like’)でも取れる
参考リンク(WordPress codex)
■投稿タイプ
https://wpdocs.osdn.jp/投稿タイプ
■WP_Meta_Query
https://wpdocs.osdn.jp/クラスリファレンス/WP_Meta_Query
あとがき・まとめ
- WPカスタムフィールドでは、複数項目のフィールドはシリアライズ化されて入っている
- meta_compareの値が『IN』や『=』では、シリアライズされたフィールドを取れない
- meta_compareの値が『REGEXP』や『like』だとヒットさせることができる
- ただし、条件によっては実行速度が一気に落ちるので、見越した設計ができるとベター
まとめるとこんなところでしょうか。今回はかなりシンプルな感じなので、割とサックリ実装できましたが、実際の運用では他の条件もかかわってきます(組み合わせによっては難しい)。シリアライズされたフィールドの取り方も押さえつつ、負荷の少ないクエリで取れるように設計できると、使うユーザーもストレスなく利用できると思うので、いろいろと検討できればと思います。 (うまく検索システム作って、管理人のサイトにも実装します)
【カテゴリ】- WordPressファンクションetc
【タグ】- WordPress, カスタムフィールド