Cum să exclud postările din subcategorii de la afișarea în categoria părinte
Am o structură de categorii pentru postări astfel:
- știri
- știri / conferințe
- știri / newsletter
În Aspect > Meniu, am adăugat 3 elemente de meniu.
Câte unul pentru fiecare categorie: Știri, Conferințe, Newsletter.
Totuși, pagina Știri afișează și postările din Conferințe și Newsletter.
Cum pot exclude postările din subcategorii de la afișarea în pagina categoriei părinte?
Mulțumesc

Am rescris codul de la un post pe WP Engineer:
function wpse_filter_child_cats( $query ) {
if ( $query->is_category ) {
$queried_object = get_queried_object();
$child_cats = (array) get_term_children( $queried_object->term_id, 'category' );
if ( ! $query->is_admin )
// exclude postările din categoriile copil
$query->set( 'category__not_in', array_merge( $child_cats ) );
}
return $query;
}
add_filter( 'pre_get_posts', 'wpse_filter_child_cats' );
Încearcă-l copiind fragmentul în fișierul tău functions.php
. Te rog să ții minte că o postare nu poate aparține atât categoriei părinte cât și categoriei copil, altfel nu va fi afișată.

Salut @1fixdotio. Mulțumesc pentru ajutor. Am adăugat acest cod în functions.php al temei mele child, dar postările din subcategorii încă apar în categoria părinte.

Ai primit vreun mesaj de eroare? Poți să-mi spui dacă ai activat permalink-ul?

@Steve Am testat codul și funcționează pe serverul meu. Tocmai l-am actualizat puțin, sper să te ajute.

Nicio eroare. Am încărcat codul actualizat și încă nu funcționează. Tema mea este o temă copil a Twenty Twelve. Vezi această pagină care conține "Prezentări de la Conferința WA Men's Shed 2012" și "The Warbler - buletinul informativ WA Men's Shed". Acestea două nu sunt în categoria părinte.

@Steve Am creat o temă copil pentru twentytwelve și am inserat codul în functions.php, a funcționat perfect. Poți dezactiva plugin-uri precum Jetpack și încerca din nou?

Tocmai am adăugat un post nou în categoria Conferences, și nu apare în pagina categoriei News, deci se pare că remediul tău funcționează pentru postări noi, dar nu și pentru postările care erau în categoria News, dar au fost mutate în subcategorii separate.

pre_get_posts
este un hook de tip acțiune, nu un hook de tip filtru. Prin urmare, ar trebui să folosești add_action()
fără a returna nimic, deoarece argumentul $query
este transmis prin referință.

Folosește category__in
în loc de cat
în interogarea ta.
După cum știi deja, cat
va interoga o categorie și subcategoriile acesteia:
$category = get_category (get_query_var('cat'));
WP_Query( 'cat'=>$category, 'post_type' => 'post' );
Cu toate acestea, atunci când folosești category__in
, nu vei obține rezultate din subcategorie.
$category = get_category (get_query_var('cat'));
WP_Query( 'category__in'=>$category, 'post_type' => 'post' );
Documentația despre interogarea bazată pe categorii se găsește aici.

Salut și bine ai venit pe WP.SE. Reține că get_category()
returnează OBJECT
, ARRAY_A,
sau ARRAY_N
. Atribuirea directă nu va funcționa. Va trebui să verifici valoarea returnată și să atribui o valoare fie prin cheia asociativă/numerică, fie prin proprietatea obiectului. Asigură-te că verifici existența acesteia înainte de a o utiliza.

Dacă doriți să includeți toate articolele care au categoria care este în prezent interogată, puteți utiliza următoarea metodă. Aceasta ar putea include potențial articole care au subcategorii ale categoriei interogate, dar numai dacă au și categoria părinte. Nu vor fi incluse articolele care au doar o subcategorie. Cu alte cuvinte, având în vedere următoarele:
Categoria 1
Categoria 2, care este o subcategorie a categoriei 1
Articolul A, care are doar categoria 1
Articolul B, care are doar categoria 2
Articolul C, care are atât categoria 1, cât și categoria 2
această interogare va returna articolele A și C, dar nu și B
function cat_query_filter($query) {
if (!is_admin() && $query->is_main_query() && is_category()) {
$queried_cat_obj = get_queried_object();
$queried_cat_id = $queried_cat_obj->term_id;
$query->set('category__in', $queried_cat_id);
}
}
add_action('pre_get_posts', 'cat_query_filter');
Răspunsul oferit de @createscape este unul bun, dar ar exclude articole precum articolul B, ceea ce poate fi sau nu ceea ce doriți. Deci, în funcție de ce doriți să fie inclus în lista de rezultate, puteți folosi fie acea soluție, fie aceasta. Informații suplimentare aici: https://developer.wordpress.org/reference/classes/wp_query/#category-parameters

Acest lucru funcționează bine și previne afișarea postărilor din categoriile copil în listarea categoriei părinte. Cu toate acestea, asigurați-vă că aveți cel puțin un articol în acea categorie părinte, altfel veți primi o eroare "not found" dacă cineva accesează elementul de meniu al categoriei părinte.

Am scris propria mea funcție pentru a exclude postările din subcategorii din buclă, deoarece am constatat că codul de mai sus nu a funcționat pentru mine.
În fișierul archive.php al temei mele, deasupra buclei, listez subcategoriile:
<?php
$current_cat = get_queried_object();
$args = array( 'parent'=>$current_cat->term_id, 'child_of' => $current_cat->term_id, );
$categories = get_categories( $args );
foreach($categories as $category) { ?>
<h2><?php echo $category->name ;?></h2>
<p> etc....</p>
<?php } ?>
În fișierul meu functions.php, am adăugat următoarea funcție personalizată folosind pre_get_posts:
add_action( 'pre_get_posts', 'main_query_without_subcategory_posts' );
function main_query_without_subcategory_posts( $query ) {
if ( ! is_admin() && $query->is_main_query() ) {
// Nu este o interogare pentru o pagină de administrare.
// Este interogarea principală pentru o pagină din partea frontală a site-ului tău.
if ( is_category() ) {
//Obține categoria curentă
$current_category = get_queried_object();
//obține ID-ul categoriei curente
$current_cat_id = $current_category->term_id;
//găsește copiii categoriei curente
$cat_args = array( 'parent'=>$current_category->term_id, 'child_of' => $current_category->term_id, );
$subcategories = get_categories( $cat_args );
//Obține o listă de ID-uri de subcategorii, adaugă un semn minus în față
$subcat_id = array();
foreach($subcategories as $subcategory) {
$subcat_id[] = " -". $subcategory->term_id;
}
//unește-le împreună ca un șir de caractere cu un separator de virgulă
$excludesubcatlist = join(',', $subcat_id);
//Dacă ai mai mulți parametri, folosește $query->set de mai multe ori
$query->set( 'posts_per_page', '10' );
$query->set( 'cat', ''.$current_cat_id.','.$excludesubcatlist.'' );
}
}
}
Apoi, în archive.php, sub subcategorii, am adăugat bucla WordPress obișnuită care este acum modificată de funcția de mai sus:
<?php while (have_posts() ) : the_post(); ?>
<h2><?php the_title();?></h2>
<p> etc....</p>
<?php endwhile;?>
Deși WordPress codex spune că folosirea "category__in" va exclude postările din subcategorii, asta nu a funcționat pentru mine și postările din subcategorii tot apăreau.
https://codex.wordpress.org/Class_Reference/WP_Query#Category_Parameters
https://developer.wordpress.org/reference/hooks/pre_get_posts/

Bine, începând cu 2019 a trebuit să folosesc un cod ușor modificat și funcționează cu orice taxonomie. Nu doar cu categoria standard. L-am folosit în configurația mea de WooCommerce și WP, prevenind afișarea produselor din categorii imbricate în categoria părinte:
add_action('parse_tax_query', 'wpse_filter_child_cats');
function wpse_filter_child_cats( $query ) {
if ( is_tax( 'product_cat' ) ) {
$queried_object = get_queried_object();
$child_cats = (array) get_term_children( $queried_object->term_id, 'product_cat' );
if ( ! $query->is_admin ) //exclude postările din categoriile copil
{
$query->tax_query->queries[] = [
'taxonomy' => 'product_cat',
'field' => 'term_id',
'terms' => array_merge( $child_cats ),
'operator' => 'NOT IN'
];
}
}
}
