Classe current-menu-item per il tipo di post personalizzato genitore
Sto avendo un problema con il mio menu e un tipo di post personalizzato.
Ho creato un tipo di post personalizzato chiamato "servizi". Ho creato una nuova pagina per esso chiamata Servizi. Su quella pagina visualizzo un elenco di tutti i post di quel tipo di post personalizzato. La classe current-menu-item funziona come previsto.
Ma il problema sorge quando clicco su uno dei servizi e vado su mysite.com/services/servizio-1, la classe current-menu-item dalla pagina Servizi nel menu scompare. Ho bisogno di mostrare che questo post corrente è un figlio della pagina Servizi.
Tutte le voci del menu hanno lo stesso 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/servizi/">Servizi</a></li>
Non c'è alcuna classe CSS che possa usare per stilizzare questo link come genitore. Qualcosa come current-menu-parent o simile. Come posso risolvere questo problema? Grazie.

Di solito includo la seguente variabile parent, filtro e metodo nei miei plugin per gestire questo caso. Non sono mai stato sicuro che questo sia il modo "giusto" di procedere, ma mi sembra meglio che applicarlo con javascript.
class Plugin_Name {
private $parent = 'services'; // idealmente questa è un'impostazione nel tuo plugin, non una variabile hard-coded nel caso in cui lo slug della pagina cambi
function __construct() {
// Aggiungi classi al '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;
// rimuovi tutte le classi attive dal menu (di solito il blog ottiene la classe current_page_parent sulle pagine/posti singoli del CPT)
$classes = array_filter($classes, ($class == 'current_page_item' || $class == 'current_page_parent' || $class == 'current_page_ancestor' || $class == 'current-menu-item' ? false : true ));
// ottieni informazioni sulla pagina
// - ci serve principalmente il post_name in modo da poterlo confrontare con lo slug del post type
$page = get_page_by_title( $item->title, OBJECT, 'page' );
// controlla se lo slug corrisponde al post_name
if( $page->post_name == $this->parent ) {
$classes[] = 'current_page_parent';
}
}
return $classes;
}
}
Come da tua richiesta, la versione senza plugin. Non ho testato questo codice per eventuali errori, l'ho solo adattato dalla classe sopra, ma dovrebbe almeno indirizzarti nella giusta direzione:
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;
// rimuovi tutte le classi attive dal menu (di solito il blog ottiene la classe current_page_parent sulle pagine/posti singoli del CPT)
$classes = array_filter($classes, ($class == 'current_page_item' || $class == 'current_page_parent' || $class == 'current_page_ancestor' || $class == 'current-menu-item' ? false : true ));
// ottieni informazioni sulla pagina
// - ci serve principalmente il post_name in modo da poterlo confrontare con lo slug del post type
$page = get_page_by_title( $item->title, OBJECT, 'page' );
// controlla se lo slug corrisponde al post_name
if( $page->post_name == $parent_slug ) {
$classes[] = 'current_page_parent';
}
}
return $classes;
}

Come potrei farlo senza utilizzare un plugin, vorrei inserirlo nel mio functions.php ma suppongo che debba essere modificato.

Ho aggiornato la mia risposta con un modo per farlo se il tuo CPT non è creato come plugin.

Questo metodo non sembra funzionare per me. Ho cambiato le variabili ma nulla. Se ho capito bene, il codice controlla il nome del post e lo confronta con lo slug? Non credo che funzionerebbe dato che il mio CPT si chiama services. Ma sto usando rewrite su "sluzby", che nella mia lingua si traduce con services. Ma i miei post di services non contengono quello slug, voglio dire che il servizio può chiamarsi Webdesign per esempio, non Service Webdesign.
Quindi la pagina che uso per visualizzare i miei post di services è localhost/wordpress/sluzby. Poi i singoli post sono su localhost/wordpress/sluzby/nome-del-post.

Sta controllando due cose: 1) Se il post visualizzato è del tuo custom post type ($cpt_name) e 2) cerca un elemento di navigazione con slug uguale a $parent_slug. Se entrambe queste condizioni sono soddisfatte, aggiunge la classe current_page_parent a quell'elemento di navigazione.

Non sono sicuro di star facendo qualcosa di sbagliato ma ancora non funziona. Ecco il mio codice attuale:
function nav_parent_class( $classes, $item ) { $cpt_name = 'services'; $parent_slug = 'sluzby';
if ...
return $classes;
}
Quindi il nome del mio custom post type è "services" e l'URL per la pagina dei servizi è localhost/wordpress/sluzby. Poi ogni servizio individuale si trova qui localhost/wordpress/sluzby/nome-del-servizio.
Ho controllato il codice sorgente ma la classe non viene aggiunta e tutte le altre classi sono scomparse. Ho anche modificato il mio CSS per includere gli stili per questa classe.

La cosa strana è che ora, quando ho commentato la riga $classes = array_filter... tutto funziona. Il che è davvero strano.

Sono contento che tu abbia risolto! Avere quella riga commentata dovrebbe andare bene. Mi preoccupa solo che, essendo commentata, ci sia una piccola possibilità che il blog (se lo hai nel tuo menu) venga evidenziato contemporaneamente quando visualizzi una singola pagina del tuo CPT.

Non ho un blog quindi va bene, forse se ce l'avessi funzionerebbe con il codice completo, senza commentare la riga delle classi :) Grazie ancora. Ho scelto la tua risposta come migliore.

Questo codice aggiunge la classe 'current-menu-item' all'elemento genitore del menu del tuo child CPT (Custom Post Type) o tassonomia personalizzata o post singolo predefinito, nel caso in cui non abbi una struttura di menu annidata nel pannello di amministrazione - solo se hai un menu di 'livello 0'. Ad esempio - se hai una Pagina Prodotti, che mostra una griglia di prodotti e vai al singolo prodotto - WordPress non vedrà l'elemento genitore del menu. Il codice seguente migliora questo comportamento:
function additional_active_item_classes( $classes = array(), $menu_item = false ) {
// tassonomia personalizzata
if ( $menu_item->title == 'Pagina Tassonomia Personalizzata' && is_tax('custom_tax') ) {
$classes[] = 'current-menu-item';
}
// custom post type singolo
if ( $menu_item->title == 'Pagina Custom Post Type' && is_singular('products') ) {
$classes[] = 'current-menu-item';
}
// articolo del blog singolo
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 );

Codice finale:
function nav_parent_class($classes, $item) {
$cpt_name = 'services';
$parent_slug = 'servizi';
if ($cpt_name == get_post_type() && !is_admin()) {
global $wpdb;
// ottieni le informazioni della pagina (ci interessa principalmente post_name per confrontarlo con lo slug del post type)
$page = get_page_by_title($item->title, OBJECT, 'page');
// controlla se lo slug corrisponde a post_name
if( $page->post_name == $parent_slug ) {
$classes[] = 'current_page_parent';
}
}
return $classes;
}
add_filter('nav_menu_css_class', 'nav_parent_class', 10, 2);

Normalmente viene aggiunta una classe .current-menu-ancestor agli elementi genitori nella navigazione.
Se non è presente, dai un'occhiata a questo articolo: Come includere la classe 'current-menu-ancestor' su un menu di un custom post type in Wordpress?

non funziona per me. Potrebbe essere perché sto usando rewrite e quindi ho nomi diversi per il custom post type e per la pagina stessa?

Questo è il codice che uso: wp_nav_menu(array( 'container' => false, 'container_class' => '', 'menu' => '', 'theme_location' => 'main-nav', 'items_wrap' => '
- %3$s

E hai il menu definito nell'area di amministrazione sotto Aspetto->Menu
. Se è così e il menu ancora non fornisce la classe, questo è un problema che non ho mai incontrato.

Sì, ho creato un Menu con tutti i link all'interno. Penso che potrebbe essere un problema con il rewrite dato che il nome del mio CPT è services ma l'URL per quella pagina è wordpress/sluzby. Sono veramente senza idee. C'è qualcos'altro che potrei provare?

Mmmh, se pensi che il problema possa essere legato al rewrite, hai provato a non fare il rewrite del CPT? Solo per confermare che le pagine figlie siano impostate come 'Voci di sottomenu' nel menu

L'ho fatto ora, non ha funzionato. Ho provato qualcos'altro però, un esempio base dal codex di WordPress per questa funzione. Eccolo:
function rm_custom_services_class($classes, $item) {
if(is_single() && $item->title == "Služby") {
$classes[] = "current_page_parent";
}
return $classes;
}
È tutto e funziona. Mi chiedevo solo se fosse possibile cambiare $item->title = "Služby" con qualcosa come $item->slug == 'sluzby'. Nel caso in cui il nome della pagina dovesse cambiare.
