Je travaille sur un site Web doté d'une fonction de recherche qui permet aux utilisateurs d'effectuer une recherche dans de nombreuses méta-publications. Il existe un modèle de recherche spécifique pour lequel je ne souhaite renvoyer aucun résultat. Techniquement, WP_Query trouvera des résultats dans la base de données, mais je voudrais l’ignorer pour le forcer à ne renvoyer aucun résultat, ce qui entraînerait l’échec de if( $example->have_posts() )
.
Existe-t-il une sorte de paramètre que je peux transmettre à WP_Query, tel que 'force_no_results' => true
, qui l'obligera à ne renvoyer aucun résultat?
Essayer
'post__in' => array(0)
Simple et au point.
Curieusement, il n’existe aucun moyen propre/explicite de court-circuiter WP_Query
.
Si c'est main query vous pourriez résoudre quelque chose autour de WP->parse_request()
, il semble y avoir un filtre relativement récent (3.5) do_parse_request
.
Mais pour WP_Query
, les hacks sont corrects, par exemple court-circuiter une requête SQL en ajoutant AND 1=0
via le filtre posts_where
, etc.
Les problèmes pour définir un paramètre de requête sur une valeur inexistante sont 2:
'posts_*'
différents ('posts_where'
, 'post_join'
, etc.) qui agissent sur la requête, vous ne pouvez donc jamais être sûr que même si vous définissez un paramètre non inexistant, la requête ne renvoie aucun résultat, une simple clause OR
renvoyée par un filtre .Vous avez besoin d'un petit peu hardcore routine pour être sûr une requête ne renvoie aucun résultat et il n'y a aucun problème de performances (ou très minime).
Pour déclencher cette routine, vous pouvez utiliser toutes les méthodes. Techniquement, vous pouvez passer n'importe quel argument à WP_Query
, des arguments d'événement inexistants.
Donc, si vous aimez quelque chose comme 'force_no_results' => true
, vous pouvez l'utiliser comme ceci:
$a = new WP_Query( array( 's' => 'foo', 'force_no_results' => true ) );
et ajoutez un callback exécuté sur 'pre_get_posts'
qui fait le travail dur:
add_action( 'pre_get_posts', function( $q ) {
if (array_key_exists('force_no_results', $q->query) && $q->query['force_no_results']) {
$q->query = $q->query_vars = array();
$added = array();
$filters = array(
'where', 'where_paged', 'join', 'join_paged', 'groupby', 'orderby', 'distinct',
'limits', 'fields', 'request', 'clauses', 'where_request', 'groupby_request',
'join_request', 'orderby_request', 'distinct_request','fields_request',
'limits_request', 'clauses_request'
);
// remove all possible interfering filter and save for later restore
foreach ( $filters as $f ) {
if ( isset($GLOBALS['wp_filter']["posts_{$f}"]) ) {
$added["posts_{$f}"] = $GLOBALS['wp_filter']["posts_{$f}"];
unset($GLOBALS['wp_filter']["posts_{$f}"]);
}
}
// be sure filters are not suppressed
$q->set( 'suppress_filters', FALSE );
$done = 0;
// use a filter to return a non-sense request
add_filter('posts_request', function( $r ) use( &$done ) {
if ( $done === 0 ) { $done = 1;
$r = "SELECT ID FROM {$GLOBALS['wpdb']->posts} WHERE 0 = 1";
}
return $r;
});
// restore any filter that was added and we removed
add_filter('posts_results', function( $posts ) use( &$done, $added ) {
if ( $done === 1 ) { $done = 2;
foreach ( $added as $hook => $filters ) {
$GLOBALS['wp_filter'][$hook] = $filters;
}
}
return $posts;
});
}
}, PHP_INT_MAX );
Ce code ne s'exécute que sur 'pre_get_posts'
le plus tard possible. Si l'argument 'force_no_results' est présent dans la requête, alors:
SELECT ID FROM wp_posts WHERE 0 = 1
une fois tous les filtres supprimés, il n'y a plus de possibilité que cette requête soit modifiée, elle est très rapide et n'a aucun résultat à coup sûr