Clasa current-menu-item pentru părintele unui custom post type
Am o problemă cu meniul meu și un custom post type.
Am un custom post type numit "servicii". Am creat o pagină nouă pentru acesta numită Servicii. Pe acea pagină afișez o listă cu toate postările din acel custom post type. Clasa current-menu-item funcționează cum trebuie.
Problema apare când fac clic pe unul dintre servicii și merg la mysite.com/servicii/serviciu-1, clasa current-menu-item de pe pagina Servicii din meniu dispare. Trebuie să arăt că această postare curentă este un copil al paginii Servicii.
Toate elementele de meniu au același HTML:
<li id="menu-item-23" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-23"><a href="http://localhost/wordpress/servicii/">Servicii</a></li>
Nu există nicio clasă CSS pe care aș putea să o folosesc pentru a stiliza acest link ca părinte. Ceva de genul current-menu-parent sau similar. Cum aș putea rezolva această problemă? Mulțumesc.

De obicei includ următoarea variabilă, filtru și metodă în plugin-urile mele pentru a gestiona acest caz. Nu am fost niciodată sigur dacă aceasta este calea "corectă" de abordare, dar pare mai bună decât aplicarea ei cu JavaScript.
class Plugin_Name {
private $parent = 'services'; // ideal ar fi ca aceasta să fie o setare în plugin, nu o variabilă hard-codată în cazul în care slug-ul paginii se schimbă
function __construct() {
// Adaugă clase la 'parent'
add_filter( 'nav_menu_css_class', array( &$this, 'nav_parent_class' ), 10, 2 );
}
function nav_parent_class( $classes, $item ) {
if ( $this->nicename == get_post_type() && ! is_admin() ) {
global $wpdb;
// elimină orice clasă activă din navigație (blog-ul primește de obicei clasa current_page_parent pe paginile/postările individuale CPT)
$classes = array_filter($classes, ($class == 'current_page_item' || $class == 'current_page_parent' || $class == 'current_page_ancestor' || $class == 'current-menu-item' ? false : true ));
// obține informațiile despre pagină
// - ne interesează doar post_name pentru a putea fi comparat cu slug-ul tipului de postare
$page = get_page_by_title( $item->title, OBJECT, 'page' );
// verifică dacă slug-ul se potrivește cu post_name
if( $page->post_name == $this->parent ) {
$classes[] = 'current_page_parent';
}
}
return $classes;
}
}
La cererea ta, varianta non-plugin. Nu am testat acest cod pentru erori, doar l-am adaptat din clasa de mai sus, dar ar trebui să te îndrepte în direcția corectă:
add_filter( 'nav_menu_css_class', 'nav_parent_class', 10, 2 );
function nav_parent_class( $classes, $item ) {
$cpt_name = 'service';
$parent_slug = 'services';
if ( $cpt_name == get_post_type() && ! is_admin() ) {
global $wpdb;
// elimină orice clasă activă din navigație (blog-ul primește de obicei clasa current_page_parent pe paginile/postările individuale CPT)
$classes = array_filter($classes, ($class == 'current_page_item' || $class == 'current_page_parent' || $class == 'current_page_ancestor' || $class == 'current-menu-item' ? false : true ));
// obține informațiile despre pagină
// - ne interesează doar post_name pentru a putea fi comparat cu slug-ul tipului de postare
$page = get_page_by_title( $item->title, OBJECT, 'page' );
// verifică dacă slug-ul se potrivește cu post_name
if( $page->post_name == $parent_slug ) {
$classes[] = 'current_page_parent';
}
}
return $classes;
}

Cum aș putea face asta fără un plugin, aș dori să-l inserez în functions.php dar presupun că trebuie modificat.

Am actualizat răspunsul meu cu o metodă de a face asta dacă CPT-ul tău nu este creat ca un plugin.

Asta nu pare să funcționeze pentru mine. Am schimbat variabilele dar tot nu merge. Dacă am înțeles corect, codul verifică numele postării și îl compară cu slug-ul? Nu cred că ar funcționa deoarece CPT-ul meu se numește "services". Dar folosesc rewrite la "sluzby", care în limba mea se traduce în "servicii". Dar postările mele de servicii nu conțin acel slug, adică serviciul poate fi numit de exemplu Webdesign, nu Service Webdesign.
Deci pagina folosită pentru afișarea postărilor mele de servicii este localhost/wordpress/sluzby. Apoi postările individuale sunt la localhost/wordpress/sluzby/numele-postului.

Verifică două lucruri: 1) Dacă postul vizualizat este din tipul tău personalizat de post ($cpt_name) și 2) caută un element de navigație cu slug-ul egal cu $parent_slug. Dacă ambele condiții se îndeplinesc, adaugă clasa current_page_parent acelui element de navigație.

Nu sunt sigur dacă fac ceva greșit, dar încă nu funcționează. Iată codul meu actual:
function nav_parent_class( $classes, $item ) { $cpt_name = 'services'; $parent_slug = 'sluzby';
if ...
return $classes;
}
Deci numele tipului meu de post personalizat este "services" și URL-ul pentru pagina de servicii este localhost/wordpress/sluzby. Apoi fiecare serviciu individual este aici localhost/wordpress/sluzby/numele-serviciului.
Am verificat codul sursă, dar clasa nu este adăugată și toate celelalte clase au dispărut. De asemenea, am modificat CSS-ul meu pentru a include și stilurile pentru această clasă.

Lucru ciudat este că acum, când am comentat linia $classes = array_filter... totul funcționează. Ceea ce este foarte ciudat.

Mă bucur că ai reușit să-l faci să funcționeze! Faptul că acea linie este comentată ar trebui să fie în regulă. Mă îngrijorează însă că, fiind comentată, există o mică șansă ca blogul (dacă îl ai în navigare) să fie evidențiat în același timp când vizualizezi o pagină singulară pentru CPT-ul tău.

Nu am un blog, așa că e în regulă, poate dacă l-aș avea ar funcționa cu codul complet, fără a comenta linia cu clasele :) Mulțumesc din nou. Am ales răspunsul tău ca fiind cel mai bun.

Acest cod adaugă clasa 'current-menu-item' elementului părinte din meniu pentru CPT-ul copil, taxonomia personalizată sau articolul standard, în cazul în care nu aveți o structură de meniu imbricată în panoul de administrare - doar dacă aveți un meniu de 'nivel 0'. De exemplu - dacă aveți o pagină Produse, care afișează o grilă de produse și accesați un singur produs - WordPress nu va recunoaște elementul părinte din meniu. Codul de mai jos îmbunătățește această situație:
function additional_active_item_classes( $classes = array(), $menu_item = false ) {
// taxonomie personalizată
if ( $menu_item->title == 'Pagina Taxonomie Personalizată' && is_tax('custom_tax') ) {
$classes[] = 'current-menu-item';
}
// post type personalizat single
if ( $menu_item->title == 'Pagina Post Type Personalizat' && is_singular('products') ) {
$classes[] = 'current-menu-item';
}
// articol blog single
if ( $menu_item->title == 'Pagina Blog' && is_singular('post') ) {
$classes[] = 'current-menu-item';
}
return $classes;
}
add_filter( 'nav_menu_css_class', 'additional_active_item_classes', 10, 2 );

Cod final:
function nav_parent_class($classes, $item) {
$cpt_name = 'services'; // Numele custom post type
$parent_slug = 'sluzby'; // Slug-ul paginii părinte
// Verificăm dacă suntem pe un post de tipul CPT și nu în admin
if ($cpt_name == get_post_type() && !is_admin()) {
global $wpdb;
// Obținem informațiile paginii (ne interesează doar post_name pentru comparație cu slug-ul CPT)
$page = get_page_by_title($item->title, OBJECT, 'page');
// Verificăm dacă slug-ul paginii se potrivește cu slug-ul părintelui
if( $page->post_name == $parent_slug ) {
$classes[] = 'current_page_parent'; // Adăugăm clasa pentru elementul părinte curent
}
}
return $classes; // Returnăm clasele modificate
}
// Adăugăm filtrul pentru clasele din meniul de navigare
add_filter('nav_menu_css_class', 'nav_parent_class', 10, 2);

În mod normal, există o clasă numită .current-menu-ancestor adăugată elementelor părinte din navigație.
Dacă această clasă lipsește, consultă acest articol: Cum să incluzi clasa 'current-menu-ancestor' pe un meniu de tip post personalizat în WordPress?

nu funcționează pentru mine. Ar putea fi din cauză că folosesc rewrite și, prin urmare, am nume diferite pentru custom post type și pentru pagina în sine?

Acesta este codul pe care îl folosesc: wp_nav_menu(array( 'container' => false, 'container_class' => '', 'menu' => '', 'theme_location' => 'main-nav', 'items_wrap' => '<ul id="menu">%3$s</ul>', 'fallback_cb' => 'rm_main_nav_fallback' ));

Și ai meniul definit în zona de administrare sub Appearance->Menus
. Dacă da, și meniul tot nu oferă clasa. Aceasta nu este o problemă pe care am întâlnit-o.

Da, am creat un Meniu cu toate linkurile în el. Cred că ar putea fi o problemă legată de rescriere, deoarece numele CPT-ului meu este services dar URL-ul pentru acea pagină este wordpress/sluzby. Sunt complet pierdut. Mai este ceva aș putea încerca?

Hmm, dacă crezi că problema ar putea fi legată de rescriere, ai încercat să nu rescrii CPT-ul? Doar pentru a confirma, paginile copil sunt setate ca 'Sub menu items' în meniu?

Am încercat acum, nu a funcționat. Am încercat altceva totuși, un exemplu de bază din codex-ul wp pentru această funcție. Iată-l:
function rm_custom_services_class($classes, $item) {
if(is_single() && $item->title == "Služby") {
$classes[] = "current_page_parent";
}
return $classes;
}
Asta e tot și funcționează. Mă întreb doar dacă este posibil să schimb $item->title = "Služby" în ceva de genul $item->slug == 'sluzby'. În caz că numele paginii s-ar schimba.
