web-dev-qa-db-fra.com

Paramètres de chaîne de requête à partir de champs personnalisés, résultats incohérents

J'ai un type de message personnalisé appelé course. Dans un post de cours, j'ai un certain nombre de champs personnalisés, en particulier (tous les menus déroulants de sélection AFC): course_or_project, time_to_complete_project, time_to_complete_course et difficulty. J'ai aussi une taxonomie appelée course_project_category.

Mon but est de pouvoir créer un certain nombre de menus déroulants/curseurs, de créer une URL en lisant les valeurs desdits menus déroulants/curseurs et, en cliquant sur un bouton de recherche, d’utiliser la chaîne de requête que j’ai assemblée (jQuery) pour filtrer uniquement les bons messages. Cette fonctionnalité fonctionne tout. Eh bien ... parfois, les résultats sont un peu confus, c’est-à-dire qu’ils ne filtrent que par certains paramètres.

Sur le code.

J'ai ajouté une fonction pour exposer mes champs personnalisés:

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');

L'interrogation de la taxonomie semble fonctionner immédiatement.

Donc, un exemple de mon URL complétée pourrait être:

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

Mes résultats sont mitigés à ce stade.

De la requête ci-dessus, j'ai renvoyé 2 publications qui correspondent pour la plupart à mes critères, mais à titre d'exemple spécifique, une publication a pour valeur time_to_complete_project la valeur 30, même si la requête a spécifié 15.

Je ne peux pas comprendre cela. Je peux voir que les paramètres sont tous là, comme prévu, dans les outils de développement de Chrome:

 enter image description here 

Des idées?!

Update

Voici une nouvelle approche qui fonctionne (mais qui manque de validation et d'hygiène):

// 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

OK, voici ce que j'ai eu à la fin. Honnêtement, je ne suis pas sûr d'avoir correctement désinfecté les paramètres, alors n'hésitez pas à entrer! Autre que cela, tout fonctionne comme prévu. Un grand merci à 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

Vous devez créer un meta_query approprié. Votre code ne fonctionnera que si vous avez un meta_key set, si vous en avez plus d'un, tout sera en ruine.

Notez également que vous devez ne jamais utiliser utiliser des valeurs non validées non validées à partir d’une variable $_GET (et même de toute valeur venant de n’importe où). Il est extrêmement facile d'injecter du code malveillant sur votre site en ajoutant un script à votre URL. La validation et l'assainissement ont très peu d'impact sur les performances, mais en valent la peine.

Pour résoudre votre problème, essayons de recoder votre action. J'ai commenté si nécessaire.

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 );

        }
    }
});

Vous pouvez affiner la requête selon vos besoins, mais ceci devrait être la base

1
Pieter Goosen