web-dev-qa-db-fra.com

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

Je vois que beaucoup de gens préfèrent utiliser pre_get_posts hook au lieu de query_posts. Le code ci-dessous fonctionne et montre tous les messages qui ont la méta clé "sélectionnée"

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 posts qui ont la méta_key 'featured' soient exclus / de la requête principale. Y at-il un moyen facile pour cela?

24
Carlisle

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

Yay!

Donc pre_get_posts filtre un objet WP_Query qui signifie n'importe quoi que vous pouvez faire via query_posts() que vous pouvez faire via $query->set() et $query->get(). En particulier, nous pouvons utiliser l'attribut meta_query (voir Codex ):

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

Mais .. ceci remplace la 'méta requête' originale (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 côtés des méta requêtes existantes.

Vous voudrez peut-être ne pas vouloir définir la propriété relation de $meta_query sur AND ou OR (pour renvoyer des publications qui satisfont à toutes les méta-requêtes ou à au moins une d'entre elles).

*Note: _ Ce type de requête renverra les publications avec la clé méta 'sélectionnée', mais dont la valeur n'est pas yes. Elle n'inclura pas les publications où la 'vedette' La méta-clé n'existe pas. Vous pourrez le faire en 3.5 .

33
Stephen Harris

Je souhaite publier ma solution temporaire pour les publications en vedette au cas où certaines personnes pourraient s'en servir. Je n'utilise pas pre_get_posts hook ici, mais pas query_posts non plus. Le problème est que je dois jouer avec la requête principale et exécuter une requête SQL. Je serais heureux si des experts pouvaient vérifier le code et me laisser savoir si tout va bien et ne causera pas de problèmes de performances. Ce serait également formidable si quelqu'un avait une meilleure approche et la partageait avec nous.

Créer une requête de messages 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 meta_key sélectionnée, limitez l'exclusion aux 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;

?>
2
Carlisle

En réponse @Carlisle, si vous souhaitez exclure les 5 publications les plus récentes sélectionnées, vous pouvez procéder comme suit. Modifiez le nombre de posts que vous souhaitez exclure avec posts_per_page et la méta_query selon la manière 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' );
0
cpeckens