Verificare se viene visualizzata una pagina di archivio di una tassonomia personalizzata

22 nov 2015, 08:41:21
Visualizzazioni: 33.4K
Voti: 6

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

Stai usando il filtro in modo errato. Questa è un'informazione molto importante che avrebbe dovuto essere inclusa nel tuo post originale. Non voglio essere scortese, ma è davvero frustrante quando si fanno giri a vuoto solo per scoprire che un'informazione fondamentale è stata omessa

Pieter Goosen Pieter Goosen
22 nov 2015 09:09:34

Per favore, sposta la soluzione che hai elaborato in una risposta separata. :) Questo è più in linea con le dinamiche del sito.

Rarst Rarst
22 nov 2015 14:40:13
Tutte le risposte alla domanda 2
5
10

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 usare has_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'hook taxonomy_template o il filtro più generico template_include.

  • Nella riga $post->post_type == 'advert' || is_tax( 'advert_category' ), sospetto che tu stia usando l'operatore sbagliato. Dovresti usare l'operatore AND. Non lo spiegherò qui perché l'ho già fatto qui. Nota che, con l'impostazione attuale, ogni volta che visualizzi un post del tipo advert, 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 di 0 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.

22 nov 2015 08:49:44
Commenti

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

Iurie Iurie
22 nov 2015 08:55:45

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

Pieter Goosen Pieter Goosen
22 nov 2015 08:57:08

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

Iurie Iurie
22 nov 2015 09:00:07

Controlla il mio aggiornamento. Spero sia quello che stavi cercando

Pieter Goosen Pieter Goosen
22 nov 2015 18:44:43

Pieter, come sempre, una risposta eccellente! Grazie mille!

Iurie Iurie
22 nov 2015 21:27:20
2

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' );
22 nov 2015 10:27:25
Commenti

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).

Iurie Iurie
22 nov 2015 10:45:56

Nessun problema! Sono contento che tu l'abbia fatto funzionare.

Luis Sanz Luis Sanz
23 nov 2015 13:04:41