web-dev-qa-db-ja.com

カスタムフィールドからの文字列パラメータのクエリ、矛盾した結果

courseというカスタム投稿タイプがあります。コースの投稿の中には、course_or_projecttime_to_complete_projecttime_to_complete_coursedifficultyというカスタムフィールドがあります。私はcourse_project_categoryという分類法もあります。

私の目的は、いくつかのドロップダウン/スライダーを作成し、ドロップダウン/スライダーの値を読んでURLを作成し、検索ボタンをクリックして、私がまとめたクエリ文字列(jQuery)を使ってフィルタリングすることです。正しい投稿この機能はすべて機能しています。うーん...時には結果が少し混乱している、つまり一部のパラメータでフィルタリングされているだけです。

コードについて.

カスタムフィールドを公開するための関数を追加しました。

function my_pre_get_posts( $query ) {

// do not modify queries in the admin
if( is_admin() ) {
    return $query;
}

// only modify queries for 'course' post type
if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'course' ) {

    // allow the url to alter the query
    if( isset($_GET['course_or_project']) ) {
        $query->set('meta_key', 'course_or_project');
        $query->set('meta_value', $_GET['course_or_project']);
    } 

    if( isset($_GET['time_to_complete_project']) ) {
        $query->set('meta_key', 'time_to_complete_project');
        $query->set('meta_value', $_GET['time_to_complete_project']);
    } 

    if( isset($_GET['time_to_complete_course']) ) {
        $query->set('meta_key', 'time_to_complete_course');
        $query->set('meta_value', $_GET['time_to_complete_course']);    
    } 

    if( isset($_GET['difficulty']) ) {    
        $query->set('meta_key', 'difficulty');
        $query->set('meta_value', $_GET['difficulty']);
    } 

}

// return
return $query;

}

add_action('pre_get_posts', 'my_pre_get_posts');

分類法を照会するのはそのままでうまくいくようです。

だから私の完成したURLの例は次のようになります。

http://localhost:3000/courses/?course_project_category=jokes&course_or_project=project&difficulty=easy&time_to_complete_project=15

私の結果は、この時点では混在しています。

上記のクエリから、私の基準にほぼ一致する2つの投稿が返されましたが、具体的な例として、クエリでtime_to_complete_projectが指定されていても1つの投稿に30の値が15として表示されます。

これがわかりません。 Chromeの開発ツールでは、パラメータがすべて期待通りに表示されていることがわかります。

enter image description here

何か案は?!

更新

これが私が持っている新しいアプローチです(しかし検証と衛生が欠けています):

// array of filters (field key => field name)
    $GLOBALS['my_query_filters'] = array( 
        'field_1'   => 'course_or_project', 
        'field_2'   => 'difficulty',
        'field_3'   => 'time_to_complete_project',
        'field_4'   => 'time_to_complete_course'
    );
// action

add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);

function my_pre_get_posts( $query ) {

    // bail early if is in admin
    if( is_admin() ) {

        return;

    }

    if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'course' ) {

        // get meta query
        $meta_query = $query->get('meta_query');


        // loop over filters
        foreach( $GLOBALS['my_query_filters'] as $key => $name ) {

            // continue if not found in url
            if( empty($_GET[ $name ]) ) {

                continue;

            }


            // get the value for this filter
            // eg: http://www.website.com/events?city=melbourne,sydney
            $value = explode(',', $_GET[ $name ]);


            // append meta query
            $meta_query[] = array(
                'key'       => $name,
                'value'     => $value,
                'compare'   => 'IN',
            );

        } 


        // update meta query
        $query->set('meta_query', $meta_query);

    }

}
1
lotech

さて、これが私が最後に働いたものです。パラメータを正しくサニタイズしたかどうかは、私は正直にわかりません。それ以外は、すべて意図したとおりに動作します。 Pieter Goosenに感謝します。

// action
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);

function my_pre_get_posts( $query ) {

    // bail early if is in admin
    if( is_admin() ) {
        return;
    }

    if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'course' ) {

        // array of filters (field key => field name)
        $GLOBALS['my_query_filters'] = array( 
            'field_1'   => 'course_or_project', 
            'field_2'   => 'difficulty',
            'field_3'   => 'time_to_complete_project',
            'field_4'   => 'time_to_complete_course'
        );

        // get meta query
        $meta_query = $query->get('meta_query');

        // loop over filters
        foreach( $GLOBALS['my_query_filters'] as $key => $name ) {

            // sanitize parameter
            $name = filter_input( INPUT_GET, $name, FILTER_SANITIZE_STRING );

            // continue if not found in url
            if( empty($_GET[ $name ]) ) {
                continue;
            }

            // get the value for this filter
            // eg: http://www.website.com/events?city=melbourne,sydney
            $value = explode(',', $_GET[ $name ]);

            // append meta query
            $meta_query[] = array(
                'key'       => $name,
                'value'     => $value,
            );

        } 

        // update meta query
        $query->set('meta_query', $meta_query);

    }

}
1
lotech

適切なmeta_queryを構築する必要があります。あなたのコードはあなたが1つのmeta_keyセットを持っているときにのみ機能するでしょう、あなたが1つ以上を持っているならば、すべてが混乱するでしょう。

また、決して$_GET変数からのサニタイズされていない、検証されていない値を使用してはいけません( そしてそれに関してはどこから来る値でも )。 URLにスクリプトを追加して悪意のあるコードをサイトに挿入するのは非常に簡単です。検証と衛生管理はパフォーマンスに与える影響はごくわずかですが、確かにその間の価値があります。

あなたの問題を解決するために、あなたの行動を書き換えてみましょう。必要に応じてコメントしました。

add_action( 'pre_get_posts', function ( $q )
{
    if (    !is_admin() // Do this only on the front end
         && $q->is_main_query() // Targets the main query only
    ) {

        if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'course' ) { // Not sure about this, can be $q->is_post_type_archive( 'course' )
            // Get all our $_GET variables and sanitize and validate them
            $course_or_project        = filter_input( INPUT_GET, 'course_or_project',        FILTER_SANITIZE_STRING );
            $time_to_complete_project = filter_input( INPUT_GET, 'time_to_complete_project', FILTER_SANITIZE_STRING ); 
            $time_to_complete_course  = filter_input( INPUT_GET, 'time_to_complete_course',  FILTER_SANITIZE_STRING );
            $difficulty               = filter_input( INPUT_GET, 'difficulty',               FILTER_VALIDATE_INT    ); 

            // Set our variable to hold the meta_query
            $meta_query = [];

            // Now we build our meta_query
            if( $course_or_project ) {
                $meta_query[] = [
                    'key'   => 'course_or_project',
                    'value' => $course_or_project
                ];
            } 

            if( $time_to_complete_project ) {
                $meta_query[] = [
                    'key'   => 'time_to_complete_project',
                    'value' => $time_to_complete_project
                ];
            } 

            if( $time_to_complete_course ) {
                $meta_query[] = [
                    'key'   => 'time_to_complete_course',
                    'value' => $time_to_complete_course    
                ];
            } 

            if( $difficulty ) {
                $meta_query[] = [
                'key'   => 'difficulty',
                'value' => $difficulty
                ];
            }

            // Make sure we have something in $meta_query before setting it
            if ( $meta_query ) 
                $q->set( 'meta_query', $meta_query );

        }
    }
});

必要に応じてクエリを絞り込むことができますが、これは非常に基本的なものです。

1
Pieter Goosen