Includere ed Escludere Tassonomie dagli Archivi e Feed con 'pre_get_posts'
Cosa sto cercando di fare?
Il mio blog utilizza una tassonomia personalizzata chiamata edizione
con termini come us-canada
(6), eu
(7) e india
(8) -- slug del termine (ID).
Voglio assicurarmi che i post non assegnati a nessuna 'edizione' specifica vengano mostrati sotto tutti i termini (cioè, se un post non è assegnato a usa, europa o india, sarà mostrato nelle pagine di archivio di tutti questi termini).
Cosa ho provato?
Ecco un esempio di codice relativo a uno dei termini, che dovrebbe darti un'idea di cosa sto cercando esattamente di fare e cosa potrei sbagliare.
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;
}
Cosa non va? Il codice sopra non funziona (ho provato anche altri: codice-1, codice-2), non cambia nulla. Non ci sono nemmeno errori di debug.
Quindi, cosa potrei sbagliare?
INOLTRE, per assicurarmi che i cambiamenti si applichino anche ai feed di questi termini, ho sostituito la riga rilevante nel codice sopra con questa:
function better_editions_archive($query) {
if ( ( $query->is_tax( 'edition', 6 ) && $query->is_main_query() ) || ( $query->is_feed() && $query->is_tax( 'edition', 6 ) ) ) {
Ma questo inizia a reindirizzare i feed dei termini nuovamente agli archivi dei termini. Cioè, con la funzione attiva, example.com/edizione/usa/feed/
reindirizza a example.com/edizione/usa/
.
Anche qui, non ho idea di cosa potrei sbagliare.
AGGIORNAMENTO: Cosa ha funzionato per me? (Ma...)
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;
}
Funziona, ma il problema è che ho avuto una lunga discussione con uno sviluppatore WordPress esperto, e mi ha detto questo (puoi seguire la conversazione completa qui, ma è molto lunga):
E stai assegnando questo array come
query_vars
. Ora,query_vars
è un oggetto piuttosto grande. E stai praticamente sovrascrivendo i dati presenti e aggiungendo solo quelli personalizzati. Questo significa che "annulli" tutto ciò che viene aggiunto per impostazione predefinita.
Mi ha praticamente sconsigliato di usare questa soluzione, suggerendo invece di usare il metodo $query->set();
.
Ma come puoi vedere sopra, non sono riuscito a far funzionare l'altro. Quindi sono qui per vedere se qualcuno può dirmi cosa sto sbagliando, con un linguaggio meno tecnico.

Proverò un altro approccio.
Il seguente codice dovrebbe modificare la query principale, in modo da includere nel suo loop qualsiasi post che non appartiene a nessun termine della tassonomia personalizzata 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;
}

Ho appena provato. Non ha cambiato nulla. Nessun errore/suggerimento di debug. Grazie per averci provato. :)

Come metodo di debug, puoi provare print_r($query) sul tuo primo codice di esempio. Da qualche parte nell'output dovrebbe esserci la SQL generata. Aggiungila qui, potrebbe essere utile.

Sì, l'ultima versione di WordPress (sempre!). E per il debug, vuoi che sostituisca return $query;
con print_r($query);
? È questo che vuoi che faccia?

Se sì, ecco cosa ho ottenuto: http://paste.kde.org/694496/ -- Dice qualcosa? (Non l'ho capito.)

Oddio, ha funzionato! E senza ulteriori modifiche sta anche modificando i feed dei termini della tassonomia personalizzata proprio come fa per gli archivi dei termini (che è esattamente ciò che voglio). Funziona davvero così o sto sognando? Non dovremmo aggiungere qualcosa come ( is_feed() && is_.... )
?

Nota per me stesso: La risposta di @vancoder è fondamentalmente una versione migliore (& automatizzata) di questa:
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;
}
(Cosa fa il codice) Se è l'archivio per qualsiasi termine che appartiene alla tassonomia personalizzata 'edition
', allora...
Il codice non interferisce con la funzione predefinita delle pagine di archivio dei termini, ovvero i post assegnati a un termine della tassonomia personalizzata '
edition
' verranno (come al solito) mostrati nell'archivio del termine rilevante.Ma se un post non è assegnato a nessuno dei termini della tassonomia personalizzata specificati (vedi
'terms' => array( 6, 7, 8 )
e'operator' => 'NOT IN'
), allora mostra tali post nelle pagine di archivio di tutti i termini della tassonomia personalizzata.Il codice influisce anche sui feed dei suddetti termini, e quindi, i feed rispecchiano il contenuto delle pagine di archivio, che è esattamente ciò di cui ho bisogno. Nel caso tu non voglia che i feed siano influenzati, cioè se vuoi che le modifiche si applichino solo alle pagine di archivio sostituisci l'IF con questo:
if ( $query->is_tax( 'edition') && $query->is_main_query() && ! $query->is_feed() ) {
