wordpressでのスマホ対応webサイト制作・wpプラグイン・PHPプログラム・SNS活用・ 動画・bgmやテーマ曲アレンジまで考えるコラム!

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

   

こんにちは、管理人@SS_mshpです。

今回は、ちょっと需要があるかもしれない『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')だと取れる


上記のgithub gistコードに書いていた、『'compare' => 'REGEXP'』でやってみた結果です。うまくシリアライズされたフィールド内に『CBR128』の値がある記事をヒットさせることができました。

実行結果~〇〇を含む('compare' => 'like')でも取れる


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

参考リンク(WordPress codex)

あとがき・まとめ

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

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

*アトリエSS・web制作サービスページに移動します。webリニューアル・ロゴ・記事・wordpress化などでお力添えできます。

【カテゴリ】 - PHP・データベースetc, webメディア制作運用
【タグ】 - , ,

  関連記事

イベントハンドラonClickとopenメソッドで、複数youtube動画をボタンで切り替え、iframe内に表示する方法

今回は管理人が、お取引先のサイトにつけようとしたけど、より便利な ...

【WordPress条件分岐】is_singleとis_singularって違うの?→idやスラッグ指定、投稿タイプ指定の面で違いが

今回は、WPの条件分岐などに使うファンクションで、名前が超似てい ...

【CSS】横並びメニューで、最初だけボーダー無しとかにしたい場合は?→擬似クラスfirst-childを、効かない例も紹介

今回は、『メニューなどで、最初の要素だけボーダー無しにしたい』み ...

cssフレームワーク利用サイトで、意図しないpaddingなどを消すには?→同クラス上書き(例:bootstrap)

今回は、CSSフレームワークなどを使ってサイトを構築していると、 ...

WP管理・投稿画面カスタマイズ~『p』『h2』みたいなタグ・定型文をボタン1つで記事に追加したい

今回は、以前サイト制作のお取引先さまと話した、WPの記事を投稿す ...

【WPプラグイン無し】3行のコードで、ブロックエディタ&ブロックライブラリCSSを無効にする方法

今回は、管理人が『お取引先さまのwebサイトでブロックエディタま ...

WPカスタムフィールドを使って、soundcloudみたいに記事一覧でオーディオ再生できるサイトを作る方法

今回は、管理人が持っている著作権フリー曲サイトに、『カスタムフィ ...