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