Verifică dacă se afișează o pagină de arhivă pentru o taxonomie personalizată

22 nov. 2015, 08:41:21
Vizualizări: 33.4K
Voturi: 6

Am un tip de postare personalizat numit 'advert' și o taxonomie personalizată aferentă numită 'advert_category', create de un plugin terț. Execut într-un plugin o instrucțiune if care trebuie să seteze (după cum mă aștept) un layout specific de temă pentru anunțuri individuale (example.com/advert/un-anunt-individual.html) și pentru paginile de arhivă ale taxonomiei personalizate (example.com/advert-category/servicii/), dar a doua condiție is_tax( 'advert_category' ) nu funcționează. Ce este greșit aici?

Codul meu:

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

Așa sunt înregistrate tipul de postare personalizat și taxonomia personalizată:

// înregistrăm tipul de postare și taxonomia pentru a permite inserarea datelor implicite
register_post_type( 'advert' ); 
register_taxonomy( 'advert_category', 'advert' );

$hid = wp_insert_post(array(
    'post_type' => 'page',
    'post_status' => 'publish',
    'post_title' => 'Anunțuri',
    'comment_status' => 'closed',
    'ping_status' => 'closed',
    'post_content' => "[adverts_list]"
));

$aid = wp_insert_post(array(
    'post_type' => 'page',
    'post_status' => 'publish',
    'post_title' => 'Adaugă',
    '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' => 'Gestionează',
    'post_parent' => $hid,
    'comment_status' => 'closed',
    'ping_status' => 'closed',
    'post_content' => "[adverts_manage]"
));

wp_insert_term(
    'Implicit',
    'advert_category'
);
2
Comentarii

Folosești filtrul greșit. Aceasta este o informație foarte importantă care ar fi trebuit să fie inclusă în postarea ta originală. Nu încerc să fiu nepoliticos, dar este foarte frustrant să mergem în cerc doar pentru a afla că informații foarte importante au fost omise

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

Te rog să muți soluția la care ai ajuns într-un răspuns separat. :) Asta se potrivește mai bine cu mecanismul site-ului.

Rarst Rarst
22 nov. 2015 14:40:13
Toate răspunsurile la întrebare 2
5
10

Ai multe probleme aici:

  • pre_get_posts nu este hook-ul corect pentru a seta template-uri. pre_get_posts este folosit pentru a modifica variabilele de interogare chiar înainte ca SQL-ul să fie construit pentru a rula interogarea principală.

  • Un filtru ar trebui întotdeauna să returneze ceva. A nu face acest lucru poate duce la comportamente neașteptate, iar uitarea acestui detaliu te poate face să pierzi ore întregi depanând problema.

  • Folosirea variabilelor globale pentru a controla funcționalități ale temei sau pentru a stoca orice fel de date este o practică proastă și nesigură. WordPress a făcut deja o mare mizerie cu variabilele globale, în special cu convențiile de denumire. Doar verifică cum începătorii (care nu cunosc WordPress) folosesc fără să știe variabile precum $post și $posts ca variabile locale. Acestea sunt variabile globale native folosite de WordPress, iar utilizarea lor ca variabile locale strică valorile acestor globale.

    Din această cauză, dacă ceva merge greșit pe pagină, nu sunt erori, așa că ești blocat încercând să depanezi ceva pe care l-ai stricat fără să știi. Variabilele globale sunt pur și simplu rele și ar trebui evitate. Gândește-te, dacă folosești variabila $wpgo_global_column_layout pentru argumentele unei interogări personalizate, vei strica valoarea template-ului care trebuie setat, template-ul tău nu se încarcă pentru că valoarea lui $wpgo_global_column_layout nu este recunoscută ca un nume de template valid, ești blocat și nu înțelegi de ce template-ul tău nu se încarcă, deși codul tău este 100% că ar trebui să încarce un template personalizat.

  • is_tax() este verificarea greșită pentru a verifica dacă un post are un anumit termen sau nu, is_tax() verifică doar dacă te afli pe o arhivă de taxonomie. Ar trebui să folosești has_term() care face exact asta, verifică dacă un anumit post are un anumit termen.

  • Dacă trebuie să setezi un template pentru o pagină de taxonomie, single_template este hook-ul greșit, ar trebui să folosești hook-ul taxonomy_template sau filtrul mai generic template_include.

  • În linia $post->post_type == 'advert' || is_tax( 'advert_category' ), bănuiesc că folosești operatorul greșit. Ar trebui să folosești operatorul AND. Nu voi explica acest lucru aici, deoarece am făcut deja ceva similar aici. Reține că, cu configurația actuală, ori de câte ori vizualizezi un post din tipul de post advert, condiția ta va returna true și se va declanșa indiferent dacă a doua condiție (is_tax( 'advert_category' )) eșuează sau nu.

  • Dacă trebuie să țintești un termen în funcție de relația părinte-copil, trebuie doar să verifici proprietatea $parent a obiectului termen. O valoare de 0 înseamnă că termenul este un părinte, orice altă valoare înseamnă că termenul este un copil/nepot/strănepot/etc.

Să renunțăm la variabilele globale proaste și să setăm template-urile corect. Nu știu exact cum tema ta setează template-urile prin $wpgo_global_column_layout, dar următoarele ar trebui să funcționeze cu prioritate. Am comentat codul pentru a fi ușor de urmărit.

PENTRU PAGINI SINGLE:

add_filter( 'single_template', function ( $template )
{
    // Elimină toate filtrele de pe filtrul curent
    remove_all_filters( current_filter(), PHP_INT_MAX );
    
    /**
     * Obține obiectul postului curent. Vom folosi get_queried_object
     * deoarece este mai sigur decât $post
     *
     * @see https://wordpress.stackexchange.com/q/167706/31545
     */
    $current_post = get_queried_object();
    
    // Verifică dacă postul curent aparține tipului de post advert, dacă nu, întoarce template-ul implicit
    if ( $current_post->post_type !== 'advert' )
        return $template;
    
    // Obține termenii postului
    $terms = get_the_terms( 
        $current_post, // Obiectul postului curent
        'advert_category' // Numele taxonomiei
    );
    
    // Dacă $terms este gol sau returnează un obiect WP_Error, întoarce template-ul implicit
    if ( !$terms || is_wp_error( $terms ) )
        return $template;
    
    /**
     * Obține primul termen și verifică dacă este un termen de nivel superior sau nu.
     * Încarcă template-ul în funcție de valoarea părintelui
     *
     * NOTĂ, acest lucru funcționează corect doar dacă postul are un singur termen
     */
    if ( $terms[0]->parent == 0 ) {
        $part = 'single-parent.php'; // Setează template-ul pentru termenii părinte
    } else {
        $part = 'single-child.php'; // Setează template-ul pentru termenii copil
    }
    
    // Verifică dacă template-ul există, dacă nu, întoarce template-ul implicit
    $locate_template = locate_template( $part );
    if ( !$locate_template ) 
        return $template;
    
    // Am ajuns aici, setează template-ul nostru personalizat
    return $template = $locate_template;
}, PHP_INT_MAX + 1 );

PENTRU PAGINI DE TAXONOMIE:

add_filter( 'taxonomy_template', function ( $template )
{
    // Elimină toate filtrele de pe filtrul curent
    remove_all_filters( current_filter(), PHP_INT_MAX );

    // Obține obiectul termenului curent. Vom folosi get_queried_object
    $current_term = get_queried_object();
    
    // Dacă termenul curent nu aparține taxonomiei advert_category, întoarce template-ul implicit
    if ( $current_term->taxonomy !== 'advert_category' )
        return $template;
    
    // Verifică dacă termenul este de nivel superior sau nu și setează template-ul în consecință
    if ( $current_term->parent == 0 ) {
        $part = 'taxonomy-parent.php'; // Setează template-ul pentru termenii părinte
    } else {
        $part = 'taxonomy-child.php'; // Setează template-ul pentru termenii copil
    }
    
    // Verifică dacă template-ul există, dacă nu, întoarce template-ul implicit
    $locate_template = locate_template( $part );
    if ( !$locate_template ) 
        return $template;
    
    // Am ajuns aici, setează template-ul nostru personalizat
    return $template = $locate_template;
}, PHP_INT_MAX + 1 );

Doar o notă, tot codul este netestat, așa că asigură-te să îl testezi local mai întâi cu debug setat pe true. De asemenea, modifică și adaptează codul pentru a-ți satisface nevoile.

22 nov. 2015 08:49:44
Comentarii

Nu funcționează :(. Din FunctionReference/has term: "Verifică dacă postarea curentă are oricare dintre termenii dați", deci, aceasta va funcționa doar pe postări individuale?

Iurie Iurie
22 nov. 2015 08:55:45

Aceasta funcționează pe pagini individuale, care este problema. Nu funcționează este foarte vag

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

Mă refer că pagina 'example.com/advert-category/services/' nu schimbă template-ul.

Iurie Iurie
22 nov. 2015 09:00:07

Verifică-mi actualizarea. Sper că asta este ceea ce cauți

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

Pieter, ca întotdeauna, un răspuns excelent! Mulțumesc mult!

Iurie Iurie
22 nov. 2015 21:27:20
2

Aveți două probleme în funcția dumneavoastră:

  • Lipseste un argument în filtrul "single_template", astfel încât filtrul nu returnează ceea ce ar trebui.
  • De asemenea, apelați has_term() fără a specifica taxonomia în care încercați să căutați.

Verificați această variantă corectă:

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
Comentarii

Am reparat câteva erori în codul meu vechi (era o variantă de testare, îmi pare rău, se pare că nu m-am trezit încă). Și am testat funcția ta, dar nu funcționează pentru paginile cu taxonomii personalizate, doar pentru postări individuale. Am găsit o soluție (vezi actualizarea).

Iurie Iurie
22 nov. 2015 10:45:56

Nicio problemă! Mă bucur că ai reușit să o faci să funcționeze.

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