Puis-je exclure un post par méta-clé à l'aide de la fonction pre_get_posts?

24

Je vois que beaucoup de gens préfèrent utiliser le pre_get_postscrochet au lieu de query_posts. Le code ci-dessous fonctionne et affiche tous les messages qui ont une méta-clé "en vedette"

function show_featured_posts ( $query ) {
    if ( $query->is_main_query() ) {
       $query->set( 'meta_key', 'featured' );
       $query->set( 'meta_value', 'yes' );
    }
}

add_action( 'pre_get_posts', 'show_featured_posts' );

Mais je veux que les messages qui ont ' featured' meta_key soient exclus de la requête principale. Existe-t-il un moyen simple pour cela?

Carlisle
la source

Réponses:

33

Je vois que beaucoup de gens préfèrent utiliser le crochet pre_get_posts au lieu de query_posts

Yay!

pre_get_postsFiltre donc un WP_Queryobjet, ce qui signifie que tout ce que vous pouvez faire via query_posts()vous pouvez le faire via $query->set()et $query->get(). En particulier, nous pouvons utiliser l' meta_queryattribut (voir Codex ):

$meta_query = array(
                 array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                 ),
);
$query->set('meta_query',$meta_query);

Mais .. cela remplace la «méta-requête» d'origine (si elle en avait une). Donc, à moins que vous ne vouliez remplacer complètement la méta-requête d'origine, je suggère:

//Get original meta query
$meta_query = $query->get('meta_query');

//Add our meta query to the original meta queries
$meta_query[] = array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                );
$query->set('meta_query',$meta_query);

De cette façon, nous ajoutons notre méta-requête aux méta-requêtes existantes.

Vous pouvez / pouvez pas définir la relationpropriété $meta_queryà ANDou OR(à des postes retour qui répondent à tous, ou au moins une, les requêtes méta).

* Remarque: ce type de requête renvoie des articles avec la méta-clé «en vedette», mais dont la valeur n'est pas yes. Il n'inclura pas les publications où la méta-clé «en vedette» n'existe pas. Vous pourrez le faire en 3.5 .

Stephen Harris
la source
Il n'y a donc aucun moyen de vérifier si une méta-clé pour une publication existe ou non / est vide ou non? Je vais devoir attendre 3,5. puis. Merci pour votre réponse.
Carlisle
Je vais simplement créer une zone de meta Yeset les Nooptions et « Non » sera sélectionné par défaut. Lorsque je souhaite publier un article, je sélectionne Yes. Cependant, je veux que les 5 derniers messages restent en vedette et que d'autres s'affichent sur la requête principale. Je ne veux pas revenir en arrière et changer la sélection à chaque fois, donc je dois trouver un moyen d'exclure uniquement les 5 derniers messages. Je vois de nombreuses questions similaires sur stackexchange et il devrait y avoir un moyen facile de gérer ces messages en vedette. (une manière qui n'affecte pas les performances générales, ne crée pas beaucoup de requêtes ou ne nécessite pas de requêtes SQL mixtes)
Carlisle
BTW Je ne sais pas si c'est une bonne idée de créer une méta-clé supplémentaire avec Yesou une Novaleur pour tous les messages. Ce serait formidable d'exclure les postes qui n'ont tout simplement pas la featuredclé.
Carlisle
Cette fonction est juste tombée en panne sur mon site après la mise à niveau vers PHP 7, lançant une Uncaught Error: [] operator not supported for stringserreur car l'original meta_queryrevenait comme nul. Vous pouvez la contourner en se repliant à un tableau vide si aucune commutation existe sur $meta_query = $query->get('meta_query');pour $meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];.
Kevin Nugent
2

Je souhaite publier ma solution temporaire pour les publications en vedette au cas où certaines personnes pourraient l'utiliser. Je n'utilise pas de pre_get_postscrochet ici mais pas non query_postsplus. Le problème est que je dois jouer avec la requête principale et exécuter un morceau de requête sql. Je serais heureux si des experts pouvaient vérifier le code et me faire savoir s'il est OK et ne causerait aucun problème de performances. Ce sera également formidable si quelqu'un a une meilleure approche et la partage avec nous.

Créer une requête de publications en vedette

<?php 

$featured_query = new WP_query( array(
    'meta_key'       =>'featured', 
    'meta_value'     =>'yes', 
    'posts_per_page' => 5, 
    'no_found_rows'  => true
    )
);

while ($featured_query->have_posts()) : 

    $featured_query->the_post(); 
    //Stuff...

endwhile; 
wp_reset_postdata(); 

?>

Créez la requête principale, excluez les publications contenant la méta-clé en vedette, limitez l'exclusion à 5 publications les plus récentes et affichez toutes les autres.

<?php 

$excludeposts = $wpdb->get_col( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'featured' AND meta_value != '' ORDER BY post_id DESC LIMIT 0, 5" );

$main_query = new WP_Query( array(
    'post__not_in' => $excludeposts, 
    'paged' => $paged 
    ) 
);  

while ($main_query->have_posts()) : 

    $main_query->the_post();
    //Stuff...

endwhile;

?>
Carlisle
la source
0

En réponse @Carlisle, si vous souhaitez exclure les 5 derniers messages marqués comme étant en vedette, vous pouvez procéder comme suit. Remplacez posts_per_page par le nombre que vous souhaitez exclure et la méta_query par la façon dont vous désignez la catégorie sélectionnée.

function cmp_exclude_featured_posts($query) {
    $exclude = array();  //Create empty array for post ids to exclude
    if ( $query->is_main_query() ) {
            $featured = get_posts(array(
                'post_type' => 'post',
                'meta_query' => array(
                    array(
                        'key' => 'featured',
                        'value' => '1',
                        'compare' => '==',
                    ),
                ),
                'posts_per_page' => 2
            ));

            foreach($featured as $hide) {
                $exclude[] = $hide->ID;
            }   

            $query->set('post__not_in', $exclude);
        }
}

add_filter( 'pre_get_posts', 'cmp_exclude_featured_posts' );
cpeckens
la source