web-dev-qa-db-fra.com

pre_get_posts: utiliser tax_query uniquement pour certains types de publication

J'ai des publications de type publication par défaut (type de publication: post) et des publications de type publication personnalisées (type de publication: cpt). Ce dernier a une taxonomie (cpt_tag).

Je voudrais afficher sur ma page d'accueil tous les articles de type d'article par défaut (non filtrés), et certains articles de type cpt, uniquement s'ils ont un certain cpt_tag.

Le code est:

add_action( 'pre_get_posts', 'get_posts_plus_cpt_with_certain_tag' );

function get_posts_plus_cpt_with_certain_tag( $query ) {
   if ( $query->is_home() && $query->is_main_query() ) {

        $taxquery = array(
            array(            
               'taxonomy' => 'cpt_tag',
               'field' => 'term_id',
               'terms' => 27
               )
            );      
        $query->set( 'tax_query', $taxquery );                 
        $query->set( 'post_type', array( 'post', 'cpt' ) );
    }
}

Le problème est que $query->set( 'tax_query', $taxquery ); est appliqué non seulement aux articles cpt, mais également aux articles post. Comment utiliser tax_query uniquement pour filtrer les publications cpt et laisser les publications post non filtrées?

Toute aide serait appréciée. Merci!

(Ceci est une version clarifiée de ma question précédente .)

1
pot63

Comme je peux le comprendre, cpt_tag est uniquement affecté au type de publication personnalisé cpt. Cela rend les choses beaucoup plus faciles et moins compliquées. Vous n'avez pas besoin de deux requêtes et vous n'avez rien à fusionner

Voici le plan:

  • Nous devons savoir quels termes vous devez afficher sur la page d'accueil à partir du type de message cpt

  • En utilisant get_terms() et le paramètre exclude, nous exclurons les termes nécessaires pour afficher les publications du type de publication cpt. Le tableau retourné par get_terms() contiendra tous les termes que nous ne voulons pas montrer. Nous allons également définir le paramètre fields sur ids afin d'obtenir un tableau d'identifiants de termes.

  • Ce tableau sera passé au tax_query dans pre_get_posts. Comme il s’agit de termes que nous devons exclure, nous allons définir le paramètre operator sur NOT IN pour exclure les publications contenant ces termes.

Vous n'avez besoin que d'ajustements mineurs à votre code pour que cela fonctionne

Voici un exemple

add_action( 'pre_get_posts', 'get_posts_plus_cpt_with_certain_tag' );

function get_posts_plus_cpt_with_certain_tag( $query ) {
    if ( $query->is_home() && $query->is_main_query() ) {

        /*
        * Change 110 to the term id you need to display posts from from cpt post type
        */
        $terms = get_terms( 'cpt_tag', array( 'exclude' => 110, 'fields' => 'ids' ) );
        if ( $terms && !is_wp_error( $terms ) ) {
            $taxquery = array(
                array(            
                    'taxonomy'  => 'cpt_tag',
                    'field'     => 'term_id',
                    'terms'     => $terms,
                    'operator'  => 'NOT IN'
                )
            );      
            $query->set('tax_query', $taxquery); 
        }   
        $query->set( 'post_type', array( 'post', 'cpt' ) );

    }
}

EDIT 1

Je n’ai pas inclus la sécurité, vous devriez vérifier d’abord si vous obtenez des résultats de get_terms avant de l’utiliser. J'ai inclus cela dans mon code maintenant

EDIT 2

La solution ci-dessus fonctionne, mais il y a un petit problème, comme indiqué dans les commentaires

... si j'ai cpt publications de type post qui n'ont pas du tout cpt_tags, le tax_query ne les filtre pas, il filtre uniquement les publications cpt avec au moins un cpt_tag...

Le problème provient du fait que les publications de type publication personnalisée par défaut ne sont pas affectées à un terme par défaut si aucun terme ne leur est attribué de la même manière que le type de publication normale post se voit attribuer le terme uncategorized par défaut lorsque aucun terme lui est attribué

Comme il n'y a pas de relation avec un terme si aucun terme ne lui est attribué, les publications de type publication personnalisées n'apparaissent pas dans la table wp_term_relationships; elles n'apparaissent donc pas dans un tax_query normal.

Pour résoudre ce problème, nous devons légèrement modifier notre flux de travail initial. Voici comment nous allons aborder ce problème

  • Obtenez tous les termes affectés au type d'article post. Par défaut, au moins un terme est attribué à toutes les publications du type de publication post à moins que ce problème ne soit modifié par un autre code radical. Nous sommes donc en sécurité à 99,999%.

  • Nous allons utiliser la même stratégie que précédemment mais avec une légère modification. Nous utiliserons toujours get_terms() avec le paramètre fields défini sur ids, mais ici nous aurons tous les termes. Je suppose que vous utilisez la taxonomie intégrée par défaut category pour le type de message post.

  • Nous pouvons simplement simplement passer les identifiants de termes dont nous avons besoin pour inclure pour le cpt_tag à notre tax_query, rien de spécial ici

  • N'oubliez pas de définir le paramètre relation sur OR car nous avons besoin de publications avec tous les termes dans category taxonomy ou toutes les publications qui ont le terme spécifique de la taxonomie cpt_tag. Si vous omettez le paramètre relation, la valeur par défaut est AND, ce qui échouera à votre requête car elle recherchera les publications qui ont des termes ayant la taxonomie category taxonomie et cpt_tag taxonomy

Alors mettons cela dans le code:

( Je vais encore utiliser le terme id 110 pour le terme pour cpt_tag, il suffit de changer en conséquence )

add_action( 'pre_get_posts', 'get_posts_plus_cpt_with_certain_tag' );

function get_posts_plus_cpt_with_certain_tag( $query ) {
    if ( $query->is_home() && $query->is_main_query() ) {

        /*
        * Change 110 to the term id you need to display posts from from cpt post type
        */
        $terms = get_terms( 'category', array( 'fields' => 'ids' ) );
        if ( $terms && !is_wp_error( $terms ) ) {
            $taxquery = array(
                'relation' => 'OR',
                array( // Includes all terms (categories) for post post type          
                    'taxonomy'  => 'category',
                    'field'     => 'term_id',
                    'terms'     => $terms,
                ),
                array( // Include the terms you need to display from cpt_tag           
                    'taxonomy'  => 'cpt_tag',
                    'field'     => 'term_id',
                    'terms'     => array( 110 ),
                ),

            );      
            $query->set('tax_query', $taxquery); 
        }   
        $query->set( 'post_type', array( 'post', 'cpt' ) );

    }
}
3
Pieter Goosen