J'ai une page d'accueil affichant le modèle home.php
, contenant 2 barres latérales avec des widgets.
La requête principale tire toujours dans les 10 posts standard, mais comme je ne les affiche pas, je voudrais éliminer complètement la requête à la base de données. Si besoin est, une boucle de publication vide fera l'affaire, car je n'utilise pas la boucle principale de mon modèle home.php
.
Comment je ferais ça? Je pourrais utiliser pre_get_posts
pour minimiser et réduire la requête, mais cela me laisse quand même avec une requête très rapide, comment puis-je l'éliminer complètement?
posts_request
En parcourant le WP_Query
, nous trouvons cette partie intéressante:
if ( !$q['suppress_filters'] ) {
/**
* Filter the completed SQL query before sending.
*
* @since 2.0.0
*
* @param array $request The complete SQL query.
* @param WP_Query &$this The WP_Query instance (passed by reference).
*/
$this->request = apply_filters_ref_array( 'posts_request',
array( $this->request, &$this ) );
}
if ( 'ids' == $q['fields'] ) {
$this->posts = $wpdb->get_col( $this->request );
$this->posts = array_map( 'intval', $this->posts );
$this->post_count = count( $this->posts );
$this->set_found_posts( $q, $limits );
return $this->posts;
}
Nous pourrions essayer d'éliminer la demande principale à la maison via le filtre posts_request
. Voici un exemple:
add_filter( 'posts_request', function( $request, \WP_Query $q )
{
// Target main home query
if ( $q->is_home() && $q->is_main_query() )
{
// Our early exit
$q->set( 'fields', 'ids' );
// No request
$request = '';
}
return $request;
}, PHP_INT_MAX, 2 );
où nous forçons le 'fields' => 'ids'
pour une sortie anticipée.
posts_pre_query
(WP 4.6+)Nous pourrions aussi utiliser le nouveau posts_pre_query
src filtre disponible dans WordPress 4.6+
add_filter( 'posts_pre_query', function( $posts, \WP_Query $q )
{
if( $q->is_home() && $q->is_main_query() )
{
$posts = [];
$q->found_posts = 0;
}
return $posts;
}, 10, 2 );
Ce filtre permet d'ignorer les requêtes de base de données habituelles pour implémenter une injection de posts personnalisée.
Je viens de tester cela et j'ai remarqué que cela n'empêcherait pas les posts collants, contrairement à l'approche posts_request
.
Découvrez le billet # 36687 pour plus d’informations et le exemple ici de @boonebgorges.
Voici une astuce intéressante que j'ai apprise de @birgire. Nous pouvons arrêter la requête principale en ajoutant AND where 0=1
à la clause WHERE
de la requête SQL. Cela peut toujours entraîner une requête de base de données, mais cela empêchera sûrement la requête principale d'interroger les publications.
add_filter( 'posts_where', function ( $where, \WP_Query $q )
{
if ( $q->is_home()
&& $q->is_main_query()
) {
$where .= ' AND where 0 = 1';
}
return $where;
}, 10, 2 );
Vous pouvez également simplement essayer de remplacer la clause WHERE
par where 0 = 1
$where = ' where 0 = 1';
au lieu de
$where .= ' AND where 0 = 1';
Malheureusement, je n'ai pas le temps de tester quoi que ce soit, mais cela devrait être un bon point de départ
Pour référence, avant: 45q, après: 42q
Le code est très similaire au code utilisé par @birgire
function _tomjn_home_cancel_query( $query, \WP_Query $q ) {
if ( !$q->is_admin() && !$q->is_feed() && $q->is_home() && $q->is_main_query() ) {
$query = false;
$q->set( 'fields', 'ids' );
}
return $query;
}
add_filter( 'posts_request', '_tomjn_home_cancel_query', 100, 2 );