メインコンテンツへ移動

Snow Monkey Search:ACFカスタムフィールドを「カスタムフィールド検索」ブロックのキーとして利用したい

0
Who liked: No user
11件の投稿を表示中 - 1 - 11件目 (全11件中)
  • 投稿者
    投稿
  • #145266
    アバター画像原子恭一
    参加者
    6

    【お使いの Snow Monkey のバージョン】29.0.0
    【お使いの Snow Monkey Blocks のバージョン】24.0.4
    【お使いの Snow Monkey Editor のバージョン】11.0.1
    【お使いのブラウザ】Google Chrome
    【当該サイトのURL】

    いつも大変お世話になっております。

    Snow Monkey Search を使用した検索機能において、またまた壁に突き当たりました。

    現在、Snow Monkey Search プラグインを利用して、カスタム投稿タイプ「レストラン」(スラッグ:restaurant)の検索システムを構築しております。
    この検索システムにおいて、Advanced Custom Fields (ACF) プラグイン(無料版)で作成したカスタムフィールドを、「カスタムフィールド検索」ブロックの絞り込み条件として利用したいと考えております。

    具体的には、以下のようなACFフィールドを絞り込み条件に追加したいです。

    最寄駅:

    フィールド名(スラッグ): access
    保存されている値の例: yaizu, shizuoka (これらを「焼津駅」「静岡駅」といったラベルで表示したい)
    対応言語:

    フィールド名(スラッグ): supported_languages
    保存されている値の例: english, chinese (これらを「英語」「中国語」といったラベルで表示したい)

    発生している問題:
    ブロックエディタで検索フォームを作成する際に、「カスタムフィールド検索」ブロックを配置し、「ブロック設定」内の「キー」のプルダウンを確認したところ、上記で作成したACFのフィールド名(access や supported_languages)が選択肢として表示されません。プルダウンには、ACF以外のメタキーと思われるものしか表示されない状況です。

    試したこと(解決には至りませんでした):
    子テーマの functions.php に add_filter( ‘snow_monkey_search_meta_keys’, …) や register_meta() を使用してACFフィールドキーを登録するようなコードを追記してみましたが、状況は改善されませんでした。
    また、REST APIエンドポイント (/wp-json/snow-monkey-search/v1/post-meta-keys/restaurant) に管理者としてログインした状態でブラウザから直接アクセスしたところ、401エラー(権限がありません)となり、キーのリストを確認できませんでした。

    ご教示いただきたい点:
    1:Snow Monkey Search の「カスタムフィールド検索」ブロックの「キー」プルダウンに、ACFで作成したカスタムフィールド名を表示させ、絞り込み条件として利用するための正しい手順をはどのようなものでしょうか。
    2:子テーマの functions.php へのカスタマイズが必要な場合、推奨される具体的なコードはどこかに記載されていますでしょうか。
    3:その他、ACFフィールドを絞り込み条件として利用するにあたり、注意すべき点や推奨される設定などがあれば、アドバイスいただけますと幸いです。

    毎度大変恐縮ですが、
    どうぞよろしくお願いいたします。

    0
    Who liked: No user
    #145267
    アバター画像キタジマ タカシ
    参加者
    2586

    んむー、なんでしょうね。

    管理画面で選択肢に表示するキーのリストは下記の部分で取得しています。

    具体的には、$wp_meta_keys というグローバル変数を参照して返却している感じです。register_meta() で登録したメタキーは $wp_meta_keys に追加されるので参照できるはずですが、ACF が内部的に register_meta() しているのかどうかは気になりますね。ACF に詳しくないためそのあたりは僕はわからないです…。

    試しに ACF を使わずに、accessregister_meta() で追加したらどうなるか確認してみると良いかもです。

    0
    Who liked: No user
    #145268
    アバター画像原子恭一
    参加者
    6

    昨夜はありがとうございました。

    おかげさまで、子テーマの functions.phpregister_meta() を使用し、対象のACFフィールドキーを明示的に登録(特に show_in_rest を適切に設定)することで、無事「キー」プルダウンにACFフィールド名が表示されるようになりました!
    ただし、新たな問題が起きました。

    新たに発生している問題:ACF複数選択チェックボックスでの絞り込みが機能しない

    キーの表示問題は解決したのですが、次に、ACFの複数選択チェックボックスで作成した「対応言語 (Language)」フィールドの絞り込みがうまく機能しないという問題に直面しております。

    現在の状況:

    1:ACFフィールド「対応言語 (Language)」の設定:

    • フィールドタイプ: チェックボックス(複数選択可)
    • 返り値: 値 (Value) (例: englishchinese
    • データベース (wp_postmeta) 保存形式: a:2:{i:0;s:7:"english";i:1;s:7:"chinese";} のようなシリアライズされた
    • 配列文字列として正しく保存されていることを確認済みです。

    2:functions.php での register_meta 設定:

    register_meta(
      'post',
      'Language',
      [
        'object_subtype' => 'restaurant', // 対象の投稿タイプ
        'single' => false,
        'type' => 'array',
        'auth_callback' => function() { return current_user_can( 'edit_posts' ); },
        'show_in_rest' => [
          'schema' => [
            'type' => 'array',
            'items' => [ 'type' => 'string' ],
          ],
        ],
      ]
    );

    (他の単一選択のACFフィールド(ラジオボタン等)は、同様に register_meta で登録し、Snow Monkey Search で問題なく絞り込みできています。)

    3:Snow Monkey Search 「カスタムフィールド検索」ブロック(Language 用)の設定:

    キー: Language
    フロー: 「チェックボックス」
    選択肢: “english”: “英語”, “chinese”: “中国語” のように設定。
    タイプ: 「CHAR (文字列)」
    比較: 「LIKE」

    4:Query Monitor で確認したSQLの問題点:
    上記のSnow Monkey Searchの設定で検索を実行したところ、メインクエリの meta_query 部分で、Language フィールドに対するSQL条件が以下のようになっていることを確認しました。
    (例:フロントで「英語」と「中国語」をチェックして検索した場合)

    AND ( ( wp_postmeta.meta_key = 'Language' ) AND ( wp_postmeta.meta_value IN ('english','chinese') ) )
    

    このSQLでは、meta_value が単純な文字列 ‘english’ または ‘chinese’ と完全一致するものを探しているため、シリアライズされた配列文字列(例: a:2:{...s:7:"english";...s:7:"chinese";...}) にはヒットせず、検索結果が0件になってしまいます。

    実現したいこと:

    ACFの複数選択チェックボックスで選択された複数の言語(例:英語と中国語)に対応しているレストランを正しく絞り込みたいです。
    理想的には、SQLが wp_postmeta.meta_value LIKE '%"english"%' AND wp_postmeta.meta_value LIKE '%"chinese"%' (AND検索の場合) や、あるいは (wp_postmeta.meta_value LIKE '%"english"%' OR wp_postmeta.meta_value LIKE '%"chinese"%') (OR検索の場合) のように、シリアライズされた配列文字列の中から選択された値の存在を LIKE で確認する形になることです。

    ご教示いただきたい点:

    1:Snow Monkey Search の「カスタムフィールド検索」ブロックは、ACFの複数選択チェックボックス(値がシリアライズされた配列としてDBに保存される)の値を、上記のような LIKE 検索で正しく絞り込むための標準的な設定方法(「タイプ」や「比較」の適切な組み合わせなど)はございますでしょうか。

    2:もし標準機能での対応が難しい場合、pre_get_posts アクションフックなどを利用して meta_query をカスタマイズする方法について、Snow Monkey Search と連携する上での推奨されるアプローチや注意点(例えば、Snow Monkey Search が生成する meta_query のどの部分を、どのように変更すればこの LIKE 検索を実現できるかなど)がございましたら、ヒントだけでもご教示いただけますと大変助かります。

    長文となり恐縮ですが、何卒よろしくお願いいたします。

    0
    Who liked: No user
    #145269
    アバター画像キタジマ タカシ
    参加者
    2586

    1:Snow Monkey Search の「カスタムフィールド検索」ブロックは、ACFの複数選択チェックボックス(値がシリアライズされた配列としてDBに保存される)の値を、上記のような LIKE 検索で正しく絞り込むための標準的な設定方法(「タイプ」や「比較」の適切な組み合わせなど)はございますでしょうか。

    本来だと同じキーのメタデータが複数登録された状態になるので、シリアライズして保存するというのが ACF の独自仕様なんですよね。なのでこれをどうにかする標準的な方法というのはなくて(強いて言えば標準的な形でメタデータを保存するプラグインに乗り換える)、基本的にはご想像の通りフックでクエリーを書き換えるという形になるのかなと思います。

    Snow Monkey Search の場合だと pre_get_posts より snow_monkey_search_pre_get_posts を使うほうが良いです。

    僕もやったことがないのでわからないのですが、meta_query の部分を参照して、書き換えた必要なメタキーが含まれていたら書き換えるというアプローチになるのかなぁと想像します。

    が、Snow Monkey Search の他に ACF にネイティブに対応している検索系プラグインがあるようなら、それを使うほうがリスクは低いかもですね…。

    0
    Who liked: No user
    #145270
    アバター画像キタジマ タカシ
    参加者
    2586

    と、ここまで書いて気づきましたが、「3:Snow Monkey Search 「カスタムフィールド検索」ブロック」にかかれているように、「比較」は「LIKE」にされてるんですよね?

    それなのに SQL では IN になっちゃうというのであれば、Snow Monkey Search 側に不具合があるのかな…?

    0
    Who liked: No user
    #145271
    アバター画像原子恭一
    参加者
    6

    はい。「比較」は「LIKE」なのに、SQL では IN になっちゃうのです。ここが大問題ですよね…

    0
    Who liked: No user
    #145272
    アバター画像キタジマ タカシ
    参加者
    2586

    試してみましたが、僕の環境だと正しく LIKE になっているようでした。

    クエリーをカスタマイズするコードを既に追加されているのであれば、一旦それを全部消してみると変化があるか確認してみてください。

    0
    Who liked: No user
    #145273
    アバター画像原子恭一
    参加者
    6

    ご確認いただきありがとうございます。

    キタジマさんの環境で LIKE になったとのこと、承知いたしました。
    追加で恐縮ですが、その際にテストされたカスタムフィールドは、
    Advanced Custom Fields (ACF) プラグインを使って作成されたフィールドでしょうか?
    それとも、ACFを使わずにWordPressの標準機能で追加されたカスタムフィールドでしょうか?

    私の環境では、ACFで作成したフィールド(値はカンマ区切りの単純な文字列としてデータベースに保存し、register_meta でも type: ‘string’, single: true で登録)に対して、
    Snow Monkey Search のカスタムフィールド検索ブロックで「タイプ:CHAR」「比較:LIKE」と設定しても、SQLが meta_value IN (‘検索語句’) となってしまいます。

    もし、キタジマさんがテストされたのがACFフィールドでない場合、
    ACFフィールドに対してSnow Monkey Search の LIKE 検索が期待通りに機能しない可能性も考えられるかと思いました…

    0
    Who liked: No user
    #145276
    アバター画像キタジマ タカシ
    参加者
    2586

    Advanced Custom Fields (ACF) プラグインを使って作成されたフィールドでしょうか?
    それとも、ACFを使わずにWordPressの標準機能で追加されたカスタムフィールドでしょうか?

    ACF ではなくて、register_meta() で追加したものです。

    Snow Monkey Search のクエリー操作を見直していて気づいたのですが、検索ボックスから特定のキーに対して複数の値が送信されてきたとき(例:チェックボックスで複数のチェックがされたとき)は、強制的に IN になるようにしてるみたいでした。

    なんで、チェックボックス検索にされているのならこれが影響しているのかも?これを消したらどうなるか一度試してみてください!

    0
    Who liked: No user
    #145277
    アバター画像原子恭一
    参加者
    6

    ご丁寧なアドバイスをいただき、ありがとうございました。

    【結果のご報告】

    ご教示いただいた内容に基づき、さらに詳細な検証を行った結果、以下の点が判明いたしました。

    1:Query.php の該当箇所について:

    ご指摘の if ( is_array( $meta_value ) ) { $meta_compare = ‘IN’; } の部分をコメントアウトしてテストしたところ、ACFの複数選択チェックボックスから送られてくる配列の $meta_value と、LIKE 検索の組み合わせでは、WordPressの WP_Meta_Query がエラーを発生させることが確認できました(wpdb->esc_like() が配列を処理できないため)。
    このことから、あのコードブロックは、配列の値に対して IN 句で検索を行うための意図的な実装であったと理解いたしました。

    2:ACF複数選択チェックボックス(値がシリアライズ配列またはカンマ区切り文字列)と Snow Monkey Search の連携について:

    現在の Snow Monkey Search の「カスタムフィールド検索」ブロックの標準機能では、データベースにシリアライズされた配列文字列やカンマ区切り文字列として保存されているACFの複数選択チェックボックスの値を、期待するような柔軟な LIKE 検索(例:選択された複数の値をOR条件やAND条件で部分一致検索する)で絞り込むことは難しい、という結論に至りました。
    (「比較:LIKE」と設定しても、実際には IN 句や、単純な文字列との完全一致に近いSQLが生成されてしまうため)

    【今後の対応について】
    1:このような複数選択が望ましい項目は、ACFのカスタムフィールドではなく、カスタムタクソノミーとして再設計し、Snow Monkey Search の「タクソノミー検索」ブロックを利用する?
    2:または、機能要件を調整し、単一選択のラジオボタンで絞り込みを行う?

    pre_get_posts フック等での高度なカスタマイズについては、とうてい私のできうる範囲ではありませんので、今回はより安定した標準的な方法を選択することになると思います。

    今回の件では、お忙しい中、何度もご丁寧にご回答いただき、ありがとうございました。

    0
    Who liked: No user
    #145278
    アバター画像原子恭一
    参加者
    6

    その後、AIが考えた以下のコードで、LIKE 検索問題は解決したかに見えましたが、
    AND検索の答えが間違っていたりして、非常に不可解な状況が続き、ここまでかな、という結論になりました。
    休日にも関わらず返信いた、だきありがとうございました。

    <?php
    // 対象のカスタムフィールドキー
    $target_field_keys = array( ‘Language’, ‘veggie-halal’ /* , 他のチェックボックス系フィールド */ );

    function fix_sms_checkbox_like_query( $query ) {
    if ( is_null( filter_input( INPUT_GET, ‘snow-monkey-search’ ) ) ) {
    return;
    }

    $meta_query = $query->get( ‘meta_query’ );
    if ( ! is_array( $meta_query ) || empty( $meta_query ) ) {
    return;
    }

    // GETパラメータからSnow Monkey Searchのカスタムフィールド設定を取得
    $post_metas_from_get = filter_input( INPUT_GET, ‘sms-post-meta’, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
    if ( ! $post_metas_from_get ) {
    return;
    }

    global $target_field_keys; // グローバル変数として定義した場合、または関数内で定義
    $modified = false;

    foreach ( $meta_query as $index => &$meta_condition ) { // 参照渡し
    if ( is_array( $meta_condition ) && isset( $meta_condition[‘key’] ) &&
    in_array( $meta_condition[‘key’], $target_field_keys ) &&
    isset( $post_metas_from_get[ $meta_condition[‘key’] ][‘compare’] ) &&
    $post_metas_from_get[ $meta_condition[‘key’] ][‘compare’] === ‘LIKE’ ) {

    if ( isset( $meta_condition[‘value’] ) && is_array( $meta_condition[‘value’] ) ) {
    $current_field_key = $meta_condition[‘key’];
    $values_from_condition = $meta_condition[‘value’];

    if ( count( $values_from_condition ) === 1 ) {
    $meta_condition[‘compare’] = ‘LIKE’;
    $meta_condition[‘value’] = $values_from_condition[0];
    $modified = true;
    } else if ( count( $values_from_condition ) > 1 ) {
    $or_conditions = array( ‘relation’ => ‘OR’ );
    foreach ( $values_from_condition as $value_item ) {
    $or_conditions[] = array(
    ‘key’ => $current_field_key,
    ‘value’ => $value_item,
    ‘compare’ => ‘LIKE’,
    ‘type’ => ‘CHAR’,
    );
    }
    $meta_condition = $or_conditions; // 元の条件をORグループで置き換え
    $modified = true;
    }
    }
    }
    }
    unset( $meta_condition );

    if ( $modified ) {
    // meta_query全体のrelation調整(複数の条件グループがある場合)
    $actual_conditions_count = 0;
    foreach ($meta_query as $mq_key => $mq_value) {
    if (is_int($mq_key)) {
    $actual_conditions_count++;
    }
    }
    if ($actual_conditions_count > 1 && !isset($meta_query[‘relation’])) {
    $meta_query[‘relation’] = ‘AND’;
    } elseif ($actual_conditions_count <= 1 && isset($meta_query[‘relation’])) {
    unset($meta_query[‘relation’]);
    }
    $query->set( ‘meta_query’, $meta_query );
    }
    // error_log(‘Final Fixed Meta Query by fix_sms_checkbox_like_query: ‘ . print_r($query->get(‘meta_query’), true));
    }
    add_action( ‘snow_monkey_search_pre_get_posts’, ‘fix_sms_checkbox_like_query’, 10 );
    ?&gt

    0
    Who liked: No user
11件の投稿を表示中 - 1 - 11件目 (全11件中)
  • このトピックに返信するにはログインが必要です。

ドキュメント

Snow Monkey の設定方法やマニュアルを掲載しています。

ドキュメント

フォーラム

Snow Monkey の使い方やカスタマイズについてのご質問・ご要望等はサポートフォーラムで行っています。サポートフォーラムは誰でも閲覧できますが、書き込みできるのは Snow Monkey 購入者のみとなります。

サポートフォーラム

よくあるご質問

Snow Monkey のサービスについて不明な点がある場合は、まずはよくあるご質問をご確認ください。

よくあるご質問

お問い合わせ

よくあるご質問を見ても解決しなかった場合、試用版の申請については問い合わせフォームからお願いいたします。

お問い合わせ

Snow Monkey は Gutenberg ブロックエディターに対応した 100%GPL の WordPress テーマです。拡張性を意識した開発をおこなっており、カスタマイザーとブロックでスピーディーにサイトを立ち上げるだけでなく、CSS やフックを駆使した高度なカスタマイズにも柔軟に対応できます。