Pot exclude o postare după meta key folosind funcția pre_get_posts?

10 nov. 2012, 01:55:57
Vizualizări: 36.3K
Voturi: 33

Văd că mulți preferă să folosească hook-ul pre_get_posts în loc de query_posts. Codul de mai jos funcționează și afișează toate postările care au meta key "featured"

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

Dar vreau ca postările care au meta_key 'featured' să fie excluse din query-ul principal. Există o modalitate simplă pentru acest lucru?

0
Toate răspunsurile la întrebare 3
4
46

Văd că mulți oameni preferă să folosească hook-ul pre_get_posts în loc de query_posts

Da!

Deci pre_get_posts filtrează un WP_Query object ceea ce înseamnă că orice ai putea face prin query_posts() poți face prin $query->set() și $query->get(). În special, putem folosi atributul meta_query (vezi Codex):

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

Dar... asta înlocuiește 'meta query'-ul original (dacă avea unul). Deci, dacă nu vrei să înlocuiești complet meta query-ul original, sugerez:

//Obține meta query-ul original
$meta_query = $query->get('meta_query');

//Adaugă meta query-ul nostru la cele existente
$meta_query[] = array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                );
$query->set('meta_query',$meta_query);

În acest fel adăugăm meta query-ul nostru alături de cele existente.

Poți dori sau nu să setezi proprietatea relation a $meta_query la AND sau OR (pentru a returna postări care satisfac toate, sau cel puțin unul, din meta query-uri).

* Notă: Acest tip de query va returna postările care au cheia meta 'featured', dar a căror valoare nu este yes. Nu va include postările unde cheia meta 'featured' nu există. Vei putea face asta în 3.5.

10 nov. 2012 12:32:19
Comentarii

Deci nu există nicio modalitate de a verifica dacă un meta_key pentru un post există sau nu / este gol sau nu? Va trebui să aștept până la versiunea 3.5. Mulțumesc pentru răspuns.

Carlisle Carlisle
10 nov. 2012 14:57:03

Voi crea pur și simplu un meta box cu opțiunile Da și Nu, iar 'Nu' va fi selectat implicit. Când voi dori să evidențiez un post, voi selecta Da. Totuși, doresc ca ultimele 5 postări să rămână evidențiate, iar restul să fie afișate în interogarea principală. Nu doresc să revin și să modific selecția de fiecare dată, așa că trebuie să găsesc o cale de a exclude doar cele mai recente 5 postări. Văd multe întrebări similare pe stackexchange și ar trebui să existe o modalitate ușoară de a gestiona aceste postări evidențiate. (o metodă care să nu afecteze performanța generală, să nu creeze multe interogări sau să necesite interogări SQL mixte)

Carlisle Carlisle
10 nov. 2012 15:38:45

Apropo, nu sunt sigur dacă este o idee bună să creez un meta_key suplimentar cu valoarea Da sau Nu pentru toate postările. Ar fi minunat să pot exclude acele postări care pur și simplu nu au cheia featured.

Carlisle Carlisle
10 nov. 2012 15:44:55

Această funcție tocmai a eșuat pe site-ul meu după actualizarea la PHP 7, aruncând o eroare Uncaught Error: [] operator not supported for strings deoarece meta_query original returna null. Poți rezolva problema prin a reveni la un array gol dacă nu există unul, înlocuind $meta_query = $query->get('meta_query'); cu $meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];.

Kevin Nugent Kevin Nugent
22 feb. 2018 13:59:06
0

Vreau să postez soluția mea temporară pentru postările recomandate, în cazul în care cineva ar putea să o folosească. Nu folosesc hook-ul pre_get_posts aici, dar nici query_posts. Problema este că trebuie să interacționez cu interogarea principală și să rulez o parte de interogare SQL. Aș fi fericit dacă vreun expert ar putea verifica codul și să-mi spună dacă este OK și nu va cauza probleme de performanță. De asemenea, ar fi minunat dacă cineva are o abordare mai bună și o poate împărtăși cu noi.

Crearea interogării pentru postările recomandate

<?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(); 
    //Conținut...

endwhile; 
wp_reset_postdata(); 

?>

Crearea interogării principale, excluderea postărilor care au meta_key 'featured', limitarea excluderii la cele mai recente 5 postări și afișarea tuturor celorlalte.

<?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();
    //Conținut...

endwhile;

?>
10 nov. 2012 18:27:34
0

Ca răspuns @Carlisle, dacă dorești să excluzi cele mai recente 5 articole marcate ca recomandate, poți face următoarele. Schimbă posts_per_page cu numărul pe care dorești să îl excluzi, iar meta_query în funcție de cum desemnezi categoria de recomandate.

function cmp_exclude_featured_posts($query) {
    $exclude = array();  //Crează un array gol pentru ID-urile postărilor de exclus
    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' );
29 apr. 2015 21:21:09