Verificare se viene visualizzata una pagina di archivio di una tassonomia personalizzata
Ho un custom post type chiamato 'advert' e una relativa tassonomia personalizzata chiamata 'advert_category', creati da un plugin di terze parti. Eseguo in un plugin un'istruzione if
che deve impostare (come mi aspetto) un layout tema specifico per gli annunci singoli (example.com/advert/a-single-advert.html) e per le pagine di archivio della tassonomia personalizzata (example.com/advert-category/services/), ma la seconda condizione is_tax( 'advert_category' )
non funziona. Cosa c'è di sbagliato qui?
Il mio codice:
function my_advert_single_template( ) {
global $post;
global $wpgo_global_column_layout;
if ( $post->post_type == 'advert' || is_tax( 'advert_category' ) ) {
$wpgo_global_column_layout = "2-col-l";
}
}
add_filter( 'single_template', 'my_advert_single_template' );
Ecco come vengono registrati il custom post type e la tassonomia personalizzata:
// registra il post type e la tassonomia per consentire l'inserimento dei dati predefiniti.
register_post_type( 'advert' );
register_taxonomy( 'advert_category', 'advert' );
$hid = wp_insert_post(array(
'post_type' => 'page',
'post_status' => 'publish',
'post_title' => 'Annunci',
'comment_status' => 'closed',
'ping_status' => 'closed',
'post_content' => "[adverts_list]"
));
$aid = wp_insert_post(array(
'post_type' => 'page',
'post_status' => 'publish',
'post_title' => 'Aggiungi',
'post_parent' => $hid,
'comment_status' => 'closed',
'ping_status' => 'closed',
'post_content' => "[adverts_add]"
));
$mid = wp_insert_post(array(
'post_type' => 'page',
'post_status' => 'publish',
'post_title' => 'Gestisci',
'post_parent' => $hid,
'comment_status' => 'closed',
'ping_status' => 'closed',
'post_content' => "[adverts_manage]"
));
wp_insert_term(
'Predefinito',
'advert_category'
);

Hai molti problemi qui:
pre_get_posts
non è l'hook corretto per impostare i template.pre_get_posts
viene utilizzato per modificare le variabili della query principale appena prima che venga costruita la SQL per eseguire la query principale.Un filtro dovrebbe sempre restituire qualcosa. Non farlo può causare comportamenti imprevisti e dimenticarsene può farti perdere ore a debug del problema.
Utilizzare globali per controllare le funzionalità del tema o per memorizzare qualsiasi tipo di dati è una cattiva pratica e non è un codice molto sicuro. WordPress ha già fatto un tale casino con le globali, in particolare con le convenzioni di denominazione. Basta vedere come i principianti (che non conoscono WordPress) utilizzano inconsapevolmente variabili come
$post
e$posts
come variabili locali. Queste sono globali native utilizzate da WordPress, e usarle come variabili locali rompe i valori di queste globali.A causa di ciò, qualcosa nella pagina va storto, non ci sono errori, quindi sei bloccato in una caccia all'oca selvatica cercando di debugare qualcosa che hai rotto inconsapevolmente. Le globali sono puro male e dovresti evitarle. Pensa solo, se usi la variabile
$wpgo_global_column_layout
per gli argomenti della query di una query personalizzata, romperai il valore del template che deve essere impostato, il tuo template non si carica perché il valore di$wpgo_global_column_layout
non è riconosciuto come un nome di template valido, sei fregato e non sai perché il tuo template non si carica anche se il tuo codice è al 100% che dovrebbe caricare un template personalizzato.is_tax()
è il controllo sbagliato da usare per verificare se un post ha un certo termine o meno,is_tax()
semplicemente controlla se sei su un archivio di tassonomia o meno. Dovresti usarehas_term()
che fa proprio questo, controlla se un certo post ha un certo termine.Se devi impostare un template per una pagina di tassonomia,
single_template
è l'hook sbagliato, dovresti usare l'hooktaxonomy_template
o il filtro più genericotemplate_include
.Nella riga
$post->post_type == 'advert' || is_tax( 'advert_category' )
, sospetto che tu stia usando l'operatore sbagliato. Dovresti usare l'operatoreAND
. Non lo spiegherò qui perché l'ho già fatto qui. Nota che, con l'impostazione attuale, ogni volta che visualizzi un post del tipoadvert
, la tua condizione restituirà true e verrà eseguita indipendentemente dal fatto che la seconda condizione (is_tax( 'advert_category' )
) fallisca o meno.Se devi targettizzare un termine in base all'ordine genitore/figlio, devi semplicemente controllare la proprietà
$parent
dell'oggetto termine. Un valore di0
significa che il termine è un genitore, qualsiasi altro valore significa che il termine è un figlio/nipote/bisnipote/ecc.
Lasciamo perdere le globali scadenti e impostiamo i template correttamente. Non so esattamente come il tuo tema imposta i template attraverso $wpgo_global_column_layout
, ma il seguente codice dovrebbe funzionare con priorità. Ho commentato il codice per renderlo facile da seguire.
PER PAGINE SINGOLE:
add_filter( 'single_template', function ( $template )
{
// Rimuovi tutti i filtri dal filtro corrente
remove_all_filters( current_filter(), PHP_INT_MAX );
/**
* Ottieni l'oggetto post corrente. Useremo get_queried_object
* perché è più sicuro da usare rispetto a $post
*
* @see https://wordpress.stackexchange.com/q/167706/31545
*/
$current_post = get_queried_object();
// Controlla se il post corrente appartiene al post type advert, altrimenti esci
if ( $current_post->post_type !== 'advert' )
return $template;
// Ottieni i termini del post
$terms = get_the_terms(
$current_post, // Oggetto post corrente
'advert_category' // Nome della tassonomia
);
// Se $terms è vuoto o restituisce un oggetto WP_Error, esci
if ( !$terms || is_wp_error( $terms ) )
return $template
/**
* Prendi il primo termine e controlla se è un termine di livello superiore o meno.
* Carica il template in base al valore del genitore
*
* NOTA, questo funziona correttamente solo se il post ha un solo termine
*/
if ( $terms[0]->parent == 0 ) {
$part = 'single-parent.php'; // Imposta il template da usare per i termini genitore
} else {
$part = 'single-child.php'; // Imposta il template per i termini figlio
}
// Controlla se il template esiste, altrimenti esci
$locate_template = locate_template( $part );
if ( !$locate_template )
return $template;
// Siamo arrivati a questo punto, imposta il nostro template personalizzato
return $template = $locate_template;
}, PHP_INT_MAX + 1 );
PER PAGINE DI TASSONOMIA:
add_filter( 'taxonomy_template', function ( $template )
{
// Rimuovi tutti i filtri dal filtro corrente
remove_all_filters( current_filter(), PHP_INT_MAX );
// Ottieni l'oggetto termine corrente. Useremo get_queried_object
$current_term = get_queried_object();
// Se il termine corrente non appartiene al post type advert, esci
if ( $current_term->taxonomy !== 'advert_category' )
return $template;
// Controlla se il termine è di livello superiore o meno e imposta il template di conseguenza
if ( $current_term->parent == 0 ) {
$part = 'taxonomy-parent.php'; // Imposta il template da usare per i termini genitore
} else {
$part = 'taxonomy-child.php'; // Imposta il template per i termini figlio
}
// Controlla se il template esiste, altrimenti esci
$locate_template = locate_template( $part );
if ( !$locate_template )
return $template;
// Siamo arrivati a questo punto, imposta il nostro template personalizzato
return $template = $locate_template;
}, PHP_INT_MAX + 1 );
Un'ultima nota, tutto il codice non è testato, quindi assicurati di testarlo localmente prima con il debug impostato su true. Inoltre modifica e abusa il codice per adattarlo alle tue esigenze.

Non funziona :(. Dalla FunctionReference/has term: "Verifica se il post corrente ha uno qualsiasi dei termini specificati", quindi, questo funzionerà solo sui singoli post?

Funziona sulle pagine singole, qual è il problema. Non funziona è davvero generico

Intendo che la pagina 'example.com/advert-category/services/' non cambia il template.

Controlla il mio aggiornamento. Spero sia quello che stavi cercando

Hai due problemi nella tua funzione:
- Manca un argomento nel filtro "single_template" e quindi il filtro non restituisce ciò che dovrebbe.
- Inoltre stai chiamando has_term() senza specificare la tassonomia in cui stai cercando.
Guarda questo:
function my_advert_single_template( $single_template ) {
global $post;
global $wpgo_global_column_layout;
if ( $post->post_type == 'advert' || has_term( 'util-categorie', 'advert_category' ) ) {
$wpgo_global_column_layout = "2-col-l";
}
return $single_template;
}
add_filter( 'single_template', 'my_advert_single_template' );

Ho corretto alcuni errori nel mio vecchio codice (era una variante di test, scusa, sembra che non mi sia ancora svegliato). E ho testato la tua funzione, ma non funziona per le pagine di tassonomia personalizzate, solo per i singoli post. E ho trovato una soluzione (vedi l'aggiornamento).
