Verifică dacă se afișează o pagină de arhivă pentru o taxonomie personalizată
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'
);
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știhas_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-ultaxonomy_template
sau filtrul mai generictemplate_include
.În linia
$post->post_type == 'advert' || is_tax( 'advert_category' )
, bănuiesc că folosești operatorul greșit. Ar trebui să folosești operatorulAND
. 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 postadvert
, 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 de0
î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.

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?

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

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

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

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