Cum să incluzi și să excluzi taxonomii din arhive și fluxuri folosind 'pre_get_posts'
Ce încerc să realizez?
Blogul meu folosește o taxonomie personalizată numită edition
cu termeni precum us-canada
(6), eu
(7) și india
(8) -- slug-ul termenului (ID).
Vreau să mă asigur că postările neatribuite unei anumite 'edition' să fie afișate sub toți termenii (adică dacă o postare nu este atribuită SUA, Europei sau Indiei, să apară în paginile de arhivă ale tuturor acestor termeni).
Ce am încercat?
Iată un exemplu de cod pentru unul dintre termeni, care ar trebui să ofere o idee despre ce încerc exact să fac și unde greșesc.
add_filter('pre_get_posts','better_editions_archive');
function better_editions_archive($query) {
if ( $query->is_tax( 'edition', 6 ) && $query->is_main_query() ) {
$query->set( 'post_type', array( 'post' ) );
$query->set( 'tax_query',
array(
'relation' => 'AND',
array(
'taxonomy' => 'category',
'field' => 'id',
'terms' => array( 1, 2, 4, 5 )
),
array(
'taxonomy' => 'edition',
'field' => 'id',
'terms' => array( 7, 8 ),
'operator' => 'NOT IN'
)
)
);
}
return $query;
}
Care e problema? Codul menționat nu funcționează (altele pe care le-am încercat: cod-1, cod-2), nu schimbă nimic. Nu apare nicio eroare de debug.
DE ASEMENEA, pentru a mă asigura că modificările se aplică și fluxurilor acestor termeni, am înlocuit linia relevantă din codul anterior cu:
function better_editions_archive($query) {
if ( ( $query->is_tax( 'edition', 6 ) && $query->is_main_query() ) || ( $query->is_feed() && $query->is_tax( 'edition', 6 ) ) ) {
Dar asta face ca fluxurile termenilor să fie redirecționate înapoi către arhivele termenilor. Adică, cu funcția activă, example.com/edition/usa/feed/
redirecționează către example.com/edition/usa/
.
ACTUALIZARE: Ce a funcționat pentru mine? (Dar...)
add_filter( 'pre_get_posts', 'better_editions_archive' );
function better_editions_archive( $query ) {
if ( $query->is_tax( 'edition', 6 ) && $query->is_main_query() ) {
$args = array(
'post_type' => 'post',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'category',
'field' => 'id',
'terms' => array( 1, 2, 4, 5 )
),
array(
'taxonomy' => 'edition',
'field' => 'id',
'terms' => array( 7, 8 ),
'operator' => 'NOT IN'
)
)
);
$query->query_vars = $args;
}
return $query;
}
Funcționează, dar problema este că am avut o discuție extinsă cu un dezvoltator WordPress cunoscător, care mi-a spus asta (puteți urmări întreaga conversație aici, dar este prea lungă):
Și apoi atribui acest array ca
query_vars
.query_vars
este un obiect destul de mare. Și practic suprascrii datele de acolo și adaugi doar cele personalizate. Asta înseamnă că 'anulezi' tot ce este adăugat implicit.
El mi-a recomandat să nu folosesc această soluție, ci să merg pe metoda $query->set();
.
Dar după cum puteți vedea mai sus, nu am reușit să fac cealaltă metodă să funcționeze. Așa că sunt aici pentru a vedea dacă cineva îmi poate spune ce greșesc, într-un limbaj mai puțin tehnic.

Voi încerca din nou.
Următorul cod ar trebui să modifice interogarea principală, astfel încât să includă în bucla sa orice articole care nu aparțin niciunui termen din taxonomia personalizată "Edition".
add_filter('pre_get_posts','better_editions_archive');
function better_editions_archive( $query ) {
if ( $query->is_tax( 'edition' ) && $query->is_main_query() ) {
$terms = get_terms( 'edition', array( 'fields' => 'ids' ) );
$query->set( 'post_type', array( 'post' ) );
$query->set( 'tax_query', array(
'relation' => 'OR',
array(
'taxonomy' => 'edition',
'field' => 'id',
'terms' => $terms,
'operator' => 'NOT IN'
)
) );
}
return $query;
}

Tocmai am încercat asta. Nu a schimbat nimic. Nici erori/sugestii de depanare. Mulțumesc pentru încercare. :)

Ca metodă de depanare, poți încerca print_r($query) în primul tău cod exemplu. În output ar trebui să fie SQL-ul generat. Adaugă-l aici, ar putea fi util.

Da, cea mai recentă versiune de WordPress (mereu!). Și pentru depanare, vrei să înlocuiesc return $query;
cu print_r($query);
? Asta vrei să fac?

Dacă da, iată ce am obținut: http://paste.kde.org/694496/ -- Spune asta ceva? (Nu am înțeles.)

Oh Doamne, a funcționat! Și fără alte modificări, modifică și feed-urile termenilor de taxonomie personalizată la fel cum face pentru arhivele termenilor (ceea ce, desigur, este ceea ce doresc). Așa funcționează sau doar visez? Nu trebuie să adăugăm ceva de genul ( is_feed() && is_.... )
?

Notă pentru mine: Răspunsul lui @vancoder este practic o versiune mai bună (& automatizată) a acestuia:
add_filter('pre_get_posts','better_editions_archive');
function better_editions_archive($query) {
if ( $query->is_tax( 'edition') && $query->is_main_query() ) {
$query->set( 'post_type', array( 'post' ) );
$query->set( 'tax_query',
array(
array(
'taxonomy' => 'edition',
'field' => 'id',
'terms' => array( 6, 7, 8 ),
'operator' => 'NOT IN'
)
)
);
}
return $query;
}
(Ce spune codul) Dacă este arhiva pentru orice termen care aparține taxonomiei personalizate 'edition
', atunci...
Codul nu interferează cu funcționalitatea implicită a paginilor de arhivă pentru termeni, adică postările atribuite unui termen din taxonomia personalizată '
edition
' vor fi (ca de obicei) afișate în arhiva termenului respectiv.Dar dacă o postare nu este atribuită niciunui dintre termenii taxonomiei specificate (vezi
'terms' => array( 6, 7, 8 )
și'operator' => 'NOT IN'
), atunci afișează astfel de postări în paginile de arhivă ale tuturor termenilor taxonomiei personalizate.Codul afectează și fluxurile RSS ale acestor termeni, astfel că fluxurile reflectă conținutul paginilor de arhivă, exact ceea ce am nevoie. În cazul în care nu doriți ca fluxurile să fie afectate, adică dacă doriți ca modificările să se aplice doar paginilor de arhivă, înlocuiți condiția IF cu aceasta:
if ( $query->is_tax( 'edition') && $query->is_main_query() && ! $query->is_feed() ) {
