webコンテンツを徹底強化!WordPressサイト制作とプラグイン&テーマ情報・メンテ/エラー対応から、PHP/CSS/javascript、動画・音・イラスト等制作まで扱うコラム
マルチメディアコンテンツ制作読んどけ☆コラム

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

      2021/02/23

【WordPressカスタムフィールド検索】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')だと取れる 上記のgithub gistコードに書いていた、『'compare' => 'REGEXP'』でやってみた結果です。うまくシリアライズされたフィールド内に『CBR128』の値がある記事をヒットさせることができました。

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

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

参考リンク(WordPress codex)

あとがき・まとめ

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

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


【カテゴリ】 - PHP・データベースetc
【タグ】 - , ,

  関連記事

【WordPressで覚えよう】PHP「->」(オブジェクト演算子/アロー演算子)・「=>」(ダブルアロー演算子)の違い

今回は、管理人もPHP学習し始めのときは混同していた、PHPの演 ...

【超危険】WordPressデータベースリビジョンお掃除

今回は、WordPressのリビジョンが、データベースに大量にた ...

【PHP】カウントダウン機能に使える?array_reverseで配列要素を逆に,パラメーター挙動&array_flipとの違い

今回は、管理人がYouTubeData APIの、order=d ...

YouTube Data APIを使って、PHPで『タイトル・動画id・サムネイル画像』などを取得してみる(Search: listリソース)

今回は、youtubeとwebサイト連携で、YouTube Da ...

テスト環境(ローカル含む)でPHPサイト開発に使えるツール&xamppでやってみた例(設定や表示ファイルetc)

今回は、管理人がサイトに、ちょっとした機能を実装しようとしていた ...

WordPress一覧表示で、特定のカテゴリ/投稿を表示しないようにするには?→category_not_in・post_not_inで

今回は、WordPressの公式フォーラムを見ていたら、『一覧か ...

WordPress・REST APIのjsonファイルにカスタムフィールドを入れ、タイトル・アイキャッチと共に外部サイトで取得・表示

今回は、管理人がWPで作ったサイトのコンテンツを、別の自社運営サ ...