Pot exclude o postare după meta key folosind funcția pre_get_posts?
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?

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.

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.

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)

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
.

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') : [];
.

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

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