Posso escludere un post con meta key usando la funzione pre_get_posts?


24

Vedo che molte persone preferiscono usare pre_get_postshook anziché query_posts. Il codice seguente funziona e mostra tutti i post che hanno la meta chiave "in primo piano"

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' );

Ma voglio che i post che hanno ' featured' meta_key siano esclusi dalla query principale. C'è un modo semplice per questo?

Risposte:


33

Vedo che molte persone preferiscono usare l'hook pre_get_posts invece di query_posts

Sìì!

Quindi pre_get_postsfiltra un WP_Queryoggetto, il che significa che tutto ciò che potresti fare tramite query_posts()te può fare tramite $query->set()e $query->get(). In particolare possiamo usare l' meta_queryattributo (vedi Codex ):

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

Ma .. questo sostituisce la "meta query" originale (se ne avesse una). Quindi, a meno che non si desideri sostituire completamente la meta query originale, suggerisco:

//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);

In questo modo aggiungiamo la nostra meta query insieme alle meta query esistenti.

Si può / non può decidere di impostare la relationproprietà di $meta_querya ANDo OR(a ritorno messaggi che soddisfano tutti, o almeno uno, meta query).

* Nota: questo tipo di query restituirà i post con la meta chiave "in primo piano", ma il cui valore non lo è yes. Non includerà post in cui non esiste la meta chiave "in primo piano". Sarai in grado di farlo in 3.5 .


Quindi non c'è modo di verificare se esiste una meta_key per un post o non è / è vuota o no? Dovrò aspettare 3.5. poi. Grazie per la tua risposta.
Carlisle,

Creerò semplicemente una meta-box con Yese Noopzioni e 'No' sarà selezionato per impostazione predefinita. Quando voglio presentare un post selezionerò Yes. Tuttavia, voglio che gli ultimi 5 post rimangano in primo piano e altri continuino a essere visualizzati nella query principale. Non voglio tornare indietro e cambiare la selezione ogni volta, quindi devo trovare un modo per escludere solo i 5 post più recenti. Vedo molte domande simili su stackexchange e dovrebbe esserci un modo semplice per gestire i post in primo piano. (un modo che non influisce sulle prestazioni generali, non crea molte query o non richiede query sql miste)
Carlisle

A proposito, non sono sicuro se sia una buona idea creare una meta_key aggiuntiva Yeso un Novalore per tutti i post. Sarebbe bello escludere quei post che semplicemente non hanno la featuredchiave.
Carlisle,

Questa funzione si è appena interrotta sul mio sito dopo l'aggiornamento a PHP 7 generando un Uncaught Error: [] operator not supported for stringserrore poiché l'originale meta_querystava tornando come nullo. È possibile aggirarlo ricadendo in un array vuoto se non esiste nessuno $meta_query = $query->get('meta_query');per cui si esce $meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];.
Kevin Nugent,

2

Voglio pubblicare la mia soluzione temporanea per i post in primo piano nel caso in cui alcune persone possano farne uso. Non uso pre_get_postshook qui, ma query_postsneanche. Il problema è che devo giocare con la query principale e eseguire una query sql. Sarei felice se qualche esperto potesse controllare il codice e farmi sapere se è OK e non causerà problemi di prestazioni. Sarebbe anche bello se qualcuno avesse un approccio migliore e lo condividesse con noi.

Crea query post in primo piano

<?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(); 

?>

Crea la query principale, escludi i post con la meta_key in primo piano, limita l'esclusione ai 5 post più recenti e mostra tutti gli altri.

<?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;

?>

0

In risposta a @Carlisle, se si desidera escludere i 5 post più recenti contrassegnati in primo piano, è possibile effettuare le seguenti operazioni. Cambia la posts_per_page in quanti vuoi escludere e la meta_query in come stai designando la categoria in evidenza.

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' );
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.