web-dev-qa-db-fra.com

the_content et is_main_query

Je filtre le contenu avec le filtre the_content. Tout fonctionne parfaitement, sauf que mes modifications sont également appliquées aux requêtes personnalisées. Mes modifications apparaissent également dans la barre latérale si le widget utilise une requête personnalisée.

Pour contrer cela, j'utilise is_main_query() pour cibler uniquement la requête principale, mais cela ne fonctionne pas. Les modifications sont simplement appliquées à toutes les requêtes. Ce qui est drôle cependant, toutes les autres vérifications conditionnelles telles que is_single() et is_category() fonctionnent si je cible des pages spécifiques, sauf que toutes les modifications affectent toute autre requête personnalisée sur cette page, que j'utilise is_main_query() ou non.

Est-ce que j'ai râté quelque chose. Comment appliquer mes modifications à la requête principale uniquement à l'aide du filtre the_content

add_filter('the_content', 'custom_content');

function custom_content($content){

    if(is_main_query()){ // << THIS IS NOT WORKING
        // My custom content that I add to the_content()    
    }
    return $content;
}
13
Pieter Goosen

Pour être honnête, la fonction in_the_loop() correspond à ce que vous recherchez:

add_filter( 'the_content', 'custom_content' );

function custom_content( $content ) {
    if ( in_the_loop() ) {
        // My custom content that I add to the_content()    
    }
    return $content;
}

Ce que in_the_loop fait, c'est vérifier si la valeur globale de $wp_query (c'est-à-dire l'objet de requête principal) de la publication en cours est -1 < $current_post < $post_count.

Cela se produit lorsque la requête principale est en boucle, car avant le début de la boucle, la publication actuelle est égale à -1 et, une fois la boucle terminée, la publication actuelle est réinitialisée à -1.

Donc, si in_the_loop() est true, cela signifie que l'objet de la requête principale est en boucle, ce dont vous avez besoin dans ce cas (et correspond au même résultat consistant à ajouter l'action sur loop_start et à supprimer sur loop_end, comme dans la réponse écrite par @ialocin; in fait cela fonctionne pour la même raison, et a obtenu mon +1).

L'approche de @ ialocin présente l'avantage de cibler un objet de requête différent de celui de l'objet principal, car in_the_loop() ne fonctionne que pour la requête principale.

11
gmazzap

Ceci est simplement un ajout à la réponse de @ Otto. Juste pour le rendre un peu mieux compréhensible. Fondamentalement, ce que @Otto dit, vous devez inverser la logique. Cela signifie que si vous pouvez déterminer de manière fiable la requête principale, vous pouvez ajouter - et supprimer - votre raccordement au filtre the_content.

Par exemple, la requête principale peut être reconnue de manière fiable à l’action pre_get_posts, de sorte que cela fonctionnerait:

function wpse162747_the_content_filter_callback( $content ) {
    return $content . 'with something appended';
}

add_action( 'pre_get_posts', 'wpse162747_pre_get_posts_callback' );
function wpse162747_pre_get_posts_callback( $query ) {
    if ( $query->is_main_query() ) {
        add_filter( 'the_content', 'wpse162747_the_content_filter_callback' );
    }
}

Comme vous êtes supposé supprimer le filtre quand il ne sera plus nécessaire, j’estime que l’action loop_end devrait être un bon endroit pour cela et que son homologue peut utiliser loop_start. Ce qui ressemblerait à ceci:

add_action( 'loop_start', 'wpse162747_loop_start_callback' );
function wpse162747_loop_start_callback( $query ) {
    if ( $query->is_main_query() ) {
        add_filter( 'the_content', 'wpse162747_the_content_filter_callback' );
    }
}

add_action( 'loop_end', 'wpse162747_loop_end_callback' );
function wpse162747_loop_end_callback( $query ) {
    if ( $query->is_main_query() ) {
        remove_filter( 'the_content', 'wpse162747_the_content_filter_callback' );
    }
}
7
Nicolai

Vous utilisez is_main_query() de manière incorrecte. La fonction globale is_main_query () renvoie true, sauf si la variable globale $ wp_query a été redéfinie.

Il n’existe probablement aucun moyen fiable à 100% de déterminer, depuis un filtre the_content, si la boucle actuelle dans laquelle vous vous trouvez est la requête principale ou non. Le filtre de contenu ne fait que filtrer le contenu. Il n'a aucune forme de capacité à savoir quelle boucle il est utilisé.

Au lieu de cela, vous devriez ajouter votre filtre lorsque vous en avez besoin, puis le supprimer lorsque vous n'en avez pas besoin.

5
Otto