Come nascondere un elemento del menu agli utenti non loggati (senza plugin)

31 lug 2016, 12:01:06
Visualizzazioni: 30.5K
Voti: 4

Voglio nascondere un elemento del menu se un utente non è loggato.

Attualmente sto usando il codice qui sotto che ottiene questo risultato usando due menu separati, ma per evitare duplicazioni, vorrei dover gestire un solo menu di navigazione.

function my_wp_nav_menu_args( $args = '' ) {

    if ( is_user_logged_in() ) { 
        $args['menu'] = 'logged-in'; // menu per utenti loggati
    } else { 
        $args['menu'] = 'logged-out'; // menu per utenti non loggati
    }

    return $args;
}
add_filter( 'wp_nav_menu_args', 'my_wp_nav_menu_args' );

È possibile nascondere solo un elemento specifico per un utente non loggato, invece di farlo nel modo in cui lo sto facendo attualmente?

3
Commenti

cosa vuoi nascondere da un menu?

mmm mmm
31 lug 2016 12:33:00

Un link che non è visibile agli utenti non registrati.

Iqbal Mahmud Iqbal Mahmud
31 lug 2016 13:02:30

La cosa "senza plugin" non è mai necessaria. Questa logica è indipendente dal tuo design e dallo stile e dovrebbe sopravvivere a un redesign del tuo sito. Mettila dentro un plugin o un mu-plugin. Avere centinaia di mini-plugin invece di un grande functions.php o un plugin estremamente grande non rallenta il tuo sito.

kaiser kaiser
31 lug 2016 15:51:15
Tutte le risposte alla domanda 7
1

Filtra wp_nav_menu_objects. Contiene la lista ordinata degli elementi del menu di navigazione da renderizzare. Dai un'occhiata a wp_setup_nav_menu_item per alcune proprietà che puoi utilizzare.

Ecco un esempio rapido (non testato).

add_filter( 'wp_nav_menu_objects', function( array $items, object $args ) {

    if ( 'someThemeLocation' !== $args->theme_location ) {
        return $items;
    }

    return array_filter( $items, function( $item ) {
        return '/user-specific-thingy' === $item->url 
            && ! is_user_logged_in();
    } );

}, 10, 2 );
31 lug 2016 15:10:36
Commenti

Questo codice non è valido, perché wp_nav_menu_objects passa array $sorted_menu_items, stdClass $args, non array $items, array $args

User User
9 mar 2023 02:28:56
2

Come @chrisguitarguy ha già fornito una risposta più che valida mentre stavo scrivendo questa risposta, ecco un semplice aggiunta alle altre due risposte.

Il valore di return della funzione wp_setup_nav_menu() ha un filtro, che riceve $menu_item come unico valore fornito – esattamente prima che venga restituito – ed è di tipo object e un \stdClass con le seguenti proprietà public che puoi verificare:

  • ID: Il term_id se la voce di menu rappresenta un termine di tassonomia.
  • attr_title: L'attributo title dell'elemento link per questa voce di menu.
  • classes: L'array dei valori dell'attributo class per l'elemento link di questa voce di menu.
  • db_id: L'ID del database di questa voce come oggetto nav_menu_item, se esiste (0 se non esiste).
  • description: La descrizione di questa voce di menu.
  • menu_item_parent: L'ID del database del nav_menu_item che è il genitore di questa voce, se presente. 0 altrimenti.
  • object: Il tipo di oggetto originariamente rappresentato, come "category", "post" o "attachment".
  • object_id: L'ID del database dell'oggetto originale che questa voce di menu rappresenta, ad esempio ID per i post e term_id per le categorie.
  • post_parent: L'ID del database dell'oggetto genitore dell'oggetto originale, se presente (0 altrimenti).
  • post_title: Un'etichetta "no title" se la voce di menu rappresenta un post che non ha un titolo.
  • target: L'attributo target dell'elemento link per questa voce di menu.
  • title: Il titolo di questa voce di menu.
  • type: La famiglia di oggetti originariamente rappresentata, come "post_type" o "taxonomy".
  • type_label: L'etichetta singolare usata per descrivere questo tipo di voce di menu.
  • url: L'URL a cui punta questa voce di menu.
  • xfn: La relazione XFN espressa nel link di questa voce di menu.
  • _invalid: Se la voce di menu rappresenta un oggetto che non esiste più.

Quindi un semplice callback ti permetterà di usare della logica condizionale e poi magari escludere una voce:

add_filter( 'wp_setup_nav_menu', function( \stdClass $item ) {
    # Verifica le condizioni e invalida una voce se necessario
    $item->_invalid = is_user_logged_in() 
        && 'post' === $item->object
        && 'post_type' === $item->type
        # && … qualsiasi altra condizione necessaria per invalidare una voce
    ;

    return $item;
} );

La logica di esclusione risiede nella proprietà _invalid ed è eseguita dalla funzione _is_valid_nav_menu_item( $item ) che è un callback usato quando le voci di menu sono recuperate. La usa all'interno di un array_filter() per ridurre il numero di voci in base a questo flag.


Come estensione alla soluzione di @MD Sultan Nasir Uddin: Sebbene una soluzione solo CSS funzioni, l'obiettivo dovrebbe essere quello di non avere nemmeno i dati in questa richiesta, nella query del database e nel pipeline di rendering. Per una risposta completa, ecco comunque il come: Esempio usando wp_add_inline_style() per incorporare gli stili e la sintassi heredoc di PHP per leggibilità:

<?php
/** Plugin Name: Nascondi voci di menu per utenti loggati */

# Aggiungi classe:
add_filter( 'wp_nav_menu_args', function( Array $args ) {
    if ( is_user_logged_in() )
        $args['menu_class'] .= '  logged-in';
    return $args;
} );

# Aggiungi stili inline
add_action( 'wp_enqueue_scripts', function() {

    $styles = <<<STYLES
.logged-in .special-item {
    display: none;
}
STYLES;

    wp_add_inline_style( 'custom-style', $styles );
} );

Potresti probabilmente usare le classi del body per trovare una classe logged-in o simile per un target più specifico – invece di aggiungere una classe aggiuntiva come sopra.

31 lug 2016 15:49:42
Commenti

Quella cosa _invalid è davvero carina.

chrisguitarguy chrisguitarguy
31 lug 2016 16:11:31

@chrisguitarguy Lo è! E non ne sapevo nulla finché non hai pubblicato la risposta e ho letto il codice sorgente. L'unica cosa di cui non sono sicuro ora è se non dovrebbe essere semplicemente false quando vuoi scartare qualcosa.

kaiser kaiser
31 lug 2016 17:41:12
1

Dopo averlo realizzato utilizzando il selettore CSS nth-child, la procedura è la seguente:

add_action('wp_head','hide_menu');

function hide_menu() { 
    if ( is_user_logged_in() ) {
        //
    } else {
        $output="<style> .menu li:nth-child(3) { display: none; } </style>";
    }
    echo $output;
}

Grazie a tutti per il vostro impegno :)

8 ago 2016 09:05:29
Commenti

Questo non funzionerà se la voce del menu cambia posizione.

Alexander Holsgrove Alexander Holsgrove
4 mar 2021 13:13:24
0

Non mi piace l'idea di nascondere semplicemente gli elementi del menu con il CSS poiché sarebbero comunque visibili utilizzando l'ispezione del codice sulla pagina. Per chi cerca un modo più sicuro per rimuovere gli elementi del menu, questo dovrebbe funzionare:

In questo esempio voglio rimuovere la voce del menu "Download" per chi non è attualmente loggato.

add_filter( 'wp_nav_menu_objects', 'remove_menu_items' ), 10, 2 );
function remove_menu_items( $items, $args ) {

    // Se devi rimuovere più voci di menu, è buona pratica impostare una variabile per il controllo in anticipo in modo che non esegua ripetutamente la stessa funzione di controllo.
    $logged_in = is_user_logged_in();

    foreach ( $items as $item_index => $item ) {
        // Rimuovi la voce "Download" quando non si è loggati
        if ( $item->title == 'Downloads' ) {
            if ( !$logged_in ) {
                unset($items[$item_index]);
            }
        }
    }
    return $items;
}
28 giu 2022 00:29:30
0

Basandomi sulla risposta di @jamio, concordo sul fatto che se usi semplicemente display:none per il menu, questo rimane comunque accessibile tramite inspect element. Per questo motivo ho trovato una soluzione: se vuoi nascondere i menu di navigazione in base alla loro classe, puoi usare classes[0] invece di title, in modo da poter semplicemente aggiungere una classe al menu invece di impostare ogni menu tramite codice.

 add_filter( 'wp_nav_menu_objects', 'remove_menu_items', 10, 2 );
function remove_menu_items( $items, $args ) {

    $logged_in = is_user_logged_in();

    foreach ( $items as $item_index => $item ) {
        // Rimuove la voce di menu con la classe "hide_when_logout" quando non si è loggati
        if ( $item->classes[0] == 'hide_when_logout' ) {
            if ( !$logged_in ) {
                unset($items[$item_index]);
            }
        }
    }
    return $items;
}
23 ott 2022 14:25:12
2
<?php
//Poi nel file header.php del tuo tema prima del tag di chiusura head usa il codice seguente
//https://wordpress.stackexchange.com/questions/233667/how-to-hide-an-item-from-a-menu-to-logged-out-users-without-a-plugin
    <?php
 if ( is_user_logged_in() ) {
       $output="<style>.menu-item-8685 {display: none !important;}</style>";
echo $output;
    } else {  
         echo '<script>alert("Benvenuto visitatore")</script>';
    }
     ?>
4 mar 2021 01:16:59
Commenti

Questa è una combinazione della risposta accettata e della risposta di Iqbal?

Rup Rup
4 mar 2021 02:26:13

sì, questa è una risposta | e ha funzionato perfettamente con me...

Mohannad Najjar Mohannad Najjar
14 mar 2021 19:36:07
3
-3

Trova la classe o l'ID della voce del menu che vuoi nascondere. Supponiamo che la classe di quel menu sia logged-in-menu

Quindi nel file header.php del tuo tema, prima del tag di chiusura head, utilizza il seguente codice:

<style>
<?php if(! is_user_logged_in() ) : ?>
    .logged-in-menu{
        display: none;
    }
<?php endif; ?>
</style>
31 lug 2016 14:07:08
Commenti

Ciò significa che stai (a) interrogando dati non necessari e (b) è non reversibile per temi figlio o plugin. Potresti almeno voler utilizzare una callback collegata a wp_head o registrare e accodare correttamente gli stili. Sebbene sarebbe una soluzione in qualche modo accettabile, sarebbe comunque preferibile disattivare condizionalmente quegli elementi prima di interrogarli dal database.

kaiser kaiser
31 lug 2016 15:03:24

Per chiunque stia pensando di usare questo metodo, per favore non fatelo. Utilizzate i proper hook dei menu come nella risposta di @chrisguitarguy.

Alexander Holsgrove Alexander Holsgrove
4 mar 2021 13:16:18

Questa è una schifezza. Qualsiasi script kiddie può comunque vedere il tuo menu.

User User
9 mar 2023 02:22:19