{"id":233913,"date":"2023-02-24T09:46:00","date_gmt":"2023-02-24T06:46:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=233913"},"modified":"2022-11-11T13:09:15","modified_gmt":"2022-11-11T10:09:15","slug":"scopri-come-scrivere-menu-walker-per-menu-wordpress","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/it\/scopri-come-scrivere-menu-walker-per-menu-wordpress\/","title":{"rendered":"Scopri come scrivere menu Walker per menu WordPress"},"content":{"rendered":"\n<p>WordPress consente di utilizzare le cosiddette classi Walker per attraversare e visualizzare elementi in una struttura gerarchica. In questo post impareremo come creare, implementare e personalizzare la nostra classe walker per personalizzare l&#8217;output del nostro menu.<\/p>\n<p>L&#8217;uso pi\u00f9 noto della personalizzazione con le classi Walker in WordPress \u00e8 per i menu, ma in realt\u00e0 WordPress utilizza le classi Walker per tutta una serie di casi, ad esempio l&#8217;output di gerarchie tassonomiche, gerarchie di commenti <code>[wp_list_pages](https:\/\/developer.wordpress.org\/reference\/functions\/wp_list_pages\/)()<\/code>e <code>[wp_list_categories](https:\/\/developer.wordpress.org\/reference\/functions\/wp_list_categories\/)()<\/code>. Tutti estendono una <code>Walker<\/code>classe generale. Estenderemo il <code>Walker_Nav_Menu<\/code>che viene utilizzato per i menu in WordPress.<\/p>\n<p>Poich\u00e9 estendiamo un&#8217;altra classe, dobbiamo solo aggiungere le funzioni che desideriamo sovrascrivere. Se una funzione non esiste nella nostra classe, WordPress eseguir\u00e0 invece la funzione &quot;classe genitore&quot; (la classe che estendiamo).<\/p>\n<h2>Preparazione<\/h2>\n<p>Puoi aggiungere la tua classe walker nei file dei plugin, nei temi <code>function.php<\/code>o in qualsiasi file PHP incluso da <code>functions.php<\/code>(per un codice pi\u00f9 pulito). Inizi definendo la tua classe con un nome a tua scelta (assicurati che il nome della classe sia univoco e questo includa i possibili nomi delle classi nel core di WordPress!) estendendo <code>Walker_Nav_Menu<\/code>:<\/p>\n<pre><code>class AWP_Menu_Walker extends Walker_Nav_Menu {\n}<\/code><\/pre>\n<p>Per dire a WordPress di utilizzare il nostro walker, lo definiamo nelle nostre <code>[wp_nav_menu](https:\/\/developer.wordpress.org\/reference\/functions\/wp_nav_menu\/)()<\/code>chiamate. Questa funzione \u00e8 responsabile dell&#8217;output di un menu e probabilmente ne hai almeno uno nel tuo tema per il menu principale.<\/p>\n<p>Nell&#8217;array di argomenti <code>wp_nav_menu()<\/code>aggiungi un nuovo elemento con la chiave &#8216;walker&#8217; e crea una nuova istanza della tua classe walker in questo modo:<\/p>\n<pre><code>wp_nav_menu([\n    'theme_location' =&gt; 'primary',\n    'menu_class' =&gt; 'main-menu',\n    'container' =&gt; 'nav',\n    'container_class' =&gt; 'header__main-nav',\n    'walker' =&gt; new AWP_Menu_Walker()\n]);<\/code><\/pre>\n<p>Se aggiorni il tuo sito non dovresti vedere alcun cambiamento. Questo perch\u00e9 la nostra classe non sovrascrive nessuna delle funzioni del genitore, e quindi WordPress esegue semplicemente le normali funzioni di menu walker durante l&#8217;output del menu, proprio come prima gli abbiamo detto di usare il nostro walker.<\/p>\n<h2>Panoramica delle funzioni in cui \u00e8 possibile eseguire l&#8217;override<code>Walker_Nav_Menu<\/code><\/h2>\n<p>Le seguenti sono funzioni che puoi aggiungere alla tua classe walker personalizzata per sovrascrivere le funzioni della classe genitoriale <code>Walker_Nav_Menu<\/code>:<\/p>\n<p>Le prime quattro sono funzioni che sono semplicemente responsabili dell&#8217;output e richiedono tutte di aggiungere una stringa, la prima variabile di parametro. \u00c8 importante sapere che qui fuori non fai <code>echo<\/code>niente, tutto dovrebbe essere costruito come una stringa.<\/p>\n<h3>start_lvl<\/h3>\n<p>La funzione <code>start_lvl<\/code>\u00e8 responsabile dell&#8217;output dell&#8217;HTML per l&#8217;inizio di un nuovo livello. In breve dovrebbe produrre l&#8217;avvio <code>&lt;ul&gt;<\/code>.<\/p>\n<pre><code>function start_lvl(&amp;$output, $depth=0, $args=null) { }<\/code><\/pre>\n<p>Il primo parametro, <code>$output<\/code>\u2013 passato per riferimento, \u00e8 la stringa a cui aggiungerai il tuo output. <code>$depth<\/code>\u00e8 un numero intero che indica a quale livello ti trovi; 0 per il livello superiore, 1 per il figlio diretto del livello superiore e cos\u00ec via. <code>$args<\/code>\u00e8 un oggetto di tutti gli argomenti forniti in <code>wp_nav_menu()<\/code>.<\/p>\n<h3>end_lvl<\/h3>\n<p>La <code>end_lvl<\/code>funzione \u00e8 responsabile dell&#8217;output dell&#8217;HTML per la fine di un livello. Di solito \u00e8 solo la chiusura <code>&lt;\/ul&gt;<\/code>.<\/p>\n<pre><code>function end_lvl(&amp;$output, $depth=0, $args=null) { }<\/code><\/pre>\n<p>I parametri sono esattamente gli stessi di <code>start_lvl<\/code>sopra.<\/p>\n<h3>start_el<\/h3>\n<p>Questa funzione \u00e8 responsabile dell&#8217;output dell&#8217;HTML di ogni elemento. In breve dovrebbe emettere l&#8217;inizio <code>&lt;li&gt;<\/code>e il <code>&lt;a&gt;<\/code>tag con il titolo del collegamento all&#8217;interno.<\/p>\n<pre><code>function start_el(&amp;$output, $item, $depth=0, $args=null, $id=0) { }<\/code><\/pre>\n<p>Il primo argomento, <code>$output<\/code>, \u00e8 come al solito la stringa a cui aggiungerai l&#8217;output. Il secondo argomento, <code>$item<\/code>, \u00e8 l&#8217;oggetto voce di menu, ed \u00e8 qui che recupererai la maggior parte dei dati per l&#8217;output della voce di menu. Se il collegamento del menu \u00e8 una voce del menu del post, qui otterrai l&#8217;oggetto del post. Indipendentemente dal tipo di menu, otterrai anche alcuni elementi utili aggiuntivi; come <code>classes<\/code>, <code>url<\/code>, <code>title<\/code>, e <code>description<\/code>.<\/p>\n<p>Il terzo argomento, <code>$depth<\/code>, \u00e8 un numero intero che ti dice a quale livello ci troviamo. Il livello 0 \u00e8 di livello superiore, 1 \u00e8 figlio diretto di livello superiore e cos\u00ec via. Il quarto argomento, <code>$args<\/code>, \u00e8 un oggetto di tutti gli argomenti forniti a <code>wp_nav_menu()<\/code>. Il quinto parametro, <code>$id<\/code>, \u00e8 l&#8217;ID della voce di menu corrente.<\/p>\n<h3>end_el<\/h3>\n<p>La <code>end_el<\/code>funzione \u00e8 responsabile dell&#8217;output della chiusura di un elemento. Di solito emetterebbe semplicemente il <code>&lt;\/li&gt;<\/code>tag.<\/p>\n<pre><code>function end_el(&amp;$output, $item, $depth=0, $args=null) { }<\/code><\/pre>\n<p>Gli argomenti per <code>end_el<\/code>sono gli stessi di cui <code>start_el<\/code>sopra, tranne per il fatto che la funzione non ha il quinto parametro, <code>$id<\/code>.<\/p>\n<h3>elemento_display<\/h3>\n<p>La funzione <code>display_element<\/code>\u00e8 una funzione ereditata dalla <code>Walker<\/code>classe generale ed \u00e8 la funzione responsabile dell&#8217;attraversamento. Questa \u00e8 la funzione che chiama a turno tutte le funzioni precedenti.<\/p>\n<p>Lo includo qui perch\u00e9 in alcuni casi, ad esempio, se vuoi impedire l&#8217;attraversamento di un intero ramo, utilizzeresti questa funzione per quello.<\/p>\n<pre><code>function display_element($element, &amp;$children_elements, $max_depth, $depth, $args, &amp;$output) { }<\/code><\/pre>\n<p>Il primo argomento, <code>$element<\/code>, \u00e8 l&#8217;oggetto voce di menu: questo \u00e8 ci\u00f2 che viene trasmesso come <code>$item<\/code>nelle funzioni precedenti. Il secondo argomento, <code>$children_elements<\/code>\u2013 passato per riferimento, contiene tutti gli elementi figlio che questa funzione attraverser\u00e0. <code>$max_depth<\/code>, il terzo argomento, \u00e8 un numero intero che indica quanto in profondit\u00e0 dovremmo attraversare e il quarto argomento, <code>$depth<\/code>, \u00e8 la profondit\u00e0 a cui ci troviamo attualmente. Il quinto argomento, <code>$args<\/code>, sono gli argomenti passati alla funzione che ha chiamato il walker (per i menu sarebbero gli argomenti forniti a <code>wp_nav_menu()<\/code>), e l&#8217;argomento finale, <code>$output<\/code>\u2013 passato per riferimento, \u00e8 l&#8217;output che viene passato come primo argomento in tutti delle funzioni di cui sopra.<\/p>\n<h2>Modifica dell&#8217;output di ogni elemento<\/h2>\n<p>Nella panoramica sopra dovresti vedere che la funzione <code>start_el()<\/code>\u00e8 quella responsabile dell&#8217;output dell&#8217;HTML per un singolo elemento di menu. Iniziamo sovrascrivendo questa funzione nella nostra classe walker con un semplice esempio.<\/p>\n<h3>Esempio: impedire l&#8217;aggiunta di collegamenti per elementi &#8216;#&#8217;<\/h3>\n<p>Assicuriamoci che qualsiasi <code>#<\/code>link &#8221; &#8216; ottenga un <code>&lt;span&gt;<\/code>elemento invece di un tag link, per evitare di aggiornare la pagina.<\/p>\n<pre><code>class AWP_Menu_Walker extends Walker_Nav_Menu {\n    function start_el(&amp;$output, $item, $depth=0, $args=[], $id=0) {\n        $output .= \"&lt;li class='\". implode(\" \", $item-&gt;classes). \"'&gt;\";\n\u00a0\n        if ($item-&gt;url &amp;&amp; $item-&gt;url != '#') {\n            $output .= '&lt;a href=\"'. $item-&gt;url. '\"&gt;';\n        } else {\n            $output .= '&lt;span&gt;';\n        }\n\u00a0\n        $output .= $item-&gt;title;\n\u00a0\n        if ($item-&gt;url &amp;&amp; $item-&gt;url != '#') {\n            $output .= '&lt;\/a&gt;';\n        } else {\n            $output .= '&lt;\/span&gt;';\n        }\n    }\n}<\/code><\/pre>\n<p>Inizieremo l&#8217;elemento aggiungendo un <code>&lt;li&gt;<\/code>tag a <code>$output<\/code>. Vogliamo assicurarci che le classi predefinite di WordPress (ad esempio &#8216;menu-item&#8217;, &#8216;menu-item-ha-children&#8217; ecc.), cos\u00ec come le classi inserite manualmente nell&#8217;editor di menu, vengano aggiunte al nostro elemento di elenco. Incolliamo le classi fornite come array <code>$item-&gt;classes<\/code>usando la funzione PHP <code>[implode](https:\/\/www.php.net\/manual\/en\/function.implode.php)()<\/code>separando ogni elemento con uno spazio.<\/p>\n<p>Alla riga #5-9 e #13-17 gestiamo l&#8217;output condizionale dell&#8217;elemento di wrapping. Produciamo un <code>&lt;a&gt;<\/code>tag, a meno che l&#8217;URL dell&#8217;elemento non sia &#8216; <code>#<\/code>&#8216;, nel qual caso forniamo <code>&lt;span&gt;<\/code>invece un tag. Alla riga n. 11 emettiamo semplicemente il testo del collegamento, che risiede in <code>$item-&gt;title<\/code>.<\/p>\n<p>Questo \u00e8 tutto ci\u00f2 di cui abbiamo bisogno per assicurarci che tutti gli elementi di menu che hanno &#8216; <code>#<\/code>&#8216; come URL non siano cliccabili!<\/p>\n<p>Se lo stai facendo in un tema con uno stile, tieni presente che potresti perdere un po&#8217; di stile se il tema ha applicato lo stile <code>&lt;a&gt;<\/code>direttamente al tag. Puoi risolverlo modificando lo stile ed eventualmente aggiungendo una classe all&#8217;elemento span.<\/p>\n<h3>Esempio: visualizzazione delle descrizioni delle voci di menu<\/h3>\n<p>Ad esempio, un&#8217;altra cosa che puoi fare qui \u00e8 emettere la descrizione del menu. Questo esiste, ma non \u00e8 attivato come predefinito. Nell&#8217;editor del menu di WordPress devi fare clic su &quot;Opzioni schermo&quot; in alto a destra e selezionare per mostrare &quot;Descrizione&quot;:<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-151802-61e4cfd7d3371.png\" data-rel=\"lightbox\" ><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-151802-61e4cfd7d3371.png\" alt=\"Scopri come scrivere menu Walker per menu WordPress\" ><\/a><\/p>\n<p>Ci\u00f2 consente all&#8217;utente di inserire una descrizione per ciascun elemento. Puoi produrre questa descrizione nella tua classe walker. Supponiamo che tu voglia mostrare solo la descrizione per gli elementi di primo livello, poich\u00e9 fa parte del design del tuo tema. Puoi semplicemente controllare se <code>$item<\/code>ha una descrizione e se <code>$depth<\/code>\u00e8 0, in questo modo:<\/p>\n<pre><code>        ...\n        $output .= $item-&gt;title;\n\u00a0\n        if ($depth == 0 &amp;&amp; !empty($item-&gt;description)) {\n            $output .= '&lt;span class=\"description\"&gt;'. $item-&gt;description. '&lt;\/span&gt;';\n        }\n        ...<\/code><\/pre>\n<h3>Esempio: aggiunta di accenti a discesa<\/h3>\n<p>Un esempio pi\u00f9 comune e utile \u00e8 l&#8217;aggiunta di un &quot;accento circonflesso&quot;, un&#8217;icona che segnala che questa voce di menu ha un menu a discesa (ha elementi figlio).<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-151802-61e4cfd965e21.png\" data-rel=\"lightbox\" ><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-151802-61e4cfd965e21.png\" alt=\"Scopri come scrivere menu Walker per menu WordPress\" ><\/a><\/p>\n<p>Esempio di accento circonflesso in azione \u2013 dietro &#8220;Blog&quot; e &#8220;Notizie&#8221;<\/p>\n<p>Avrai bisogno di capire il tuo output HTML con accento circonflesso. Nel mio caso sto generando un <code>&lt;i&gt;<\/code>elemento con classi specifiche per una bella freccia in gi\u00f9 disponibile dalla libreria <a href=\"https:\/\/fontawesome.com\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Fontawesome<\/a> che fornisce migliaia di icone. Vuoi anche assicurarti che questo accento circonflesso produca solo gli elementi che hanno figli. Il modo migliore che ho trovato per capire se l&#8217;elemento corrente ha figli \u00e8 fare riferimento all&#8217;oggetto walker (s\u00ec, che \u00e8 il nostro walker stesso, ma anche le classi che estende!) in <code>$args<\/code>e controllando il boolean <code>has_children<\/code>. L&#8217;output di un accento circonflesso \u00e8 semplice come:<\/p>\n<pre><code>if ($args-&gt;walker-&gt;has_children) {\n    $output .= '&lt;i class=\"caret fa fa-angle-down\"&gt;&lt;\/i&gt;';\n}<\/code><\/pre>\n<p>La classe completa del deambulatore sarebbe simile a questa:<\/p>\n<pre><code>class AWP_Menu_Walker extends Walker_Nav_Menu {\n    function start_el(&amp;$output, $item, $depth=0, $args=[], $id=0) {\n        $output .= \"&lt;li class='\". implode(\" \", $item-&gt;classes). \"'&gt;\";\n\u00a0\n        if ($item-&gt;url &amp;&amp; $item-&gt;url != '#') {\n            $output .= '&lt;a href=\"'. $item-&gt;url. '\"&gt;';\n        } else {\n            $output .= '&lt;span&gt;';\n        }\n\u00a0\n        $output .= $item-&gt;title;\n\u00a0\n        if ($item-&gt;url &amp;&amp; $item-&gt;url != '#') {\n            $output .= '&lt;\/a&gt;';\n        } else {\n            $output .= '&lt;\/span&gt;';\n        }\n\u00a0\n        if ($args-&gt;walker-&gt;has_children) {\n            $output .= '&lt;i class=\"caret fa fa-angle-down\"&gt;&lt;\/i&gt;';\n        }\n    }\n}<\/code><\/pre>\n<p>E questo \u00e8 tutto ci\u00f2 di cui hai bisogno per assicurarti che il tuo menu ottenga delle belle icone di accento circonflesso sugli elementi principali e che <code>#<\/code>i collegamenti &quot; &quot; non siano cliccabili.<\/p>\n<p>Se vuoi che l&#8217;icona del cursore cambi, ad esempio in una freccia su quando il menu a discesa \u00e8 attivo, dovrai aggiungerlo con Javascript al tuo tema.<\/p>\n<p>Come suggeriscono gli esempi precedenti, puoi manipolare l&#8217;output come preferisci, in base a qualsiasi condizione. Ad esempio, puoi modificare l&#8217;output in base alla presenza di una determinata classe (ad esempio una classe inserita manualmente nell&#8217;editor di menu) cercando la classe in <code>$item-&gt;classes<\/code>, oppure puoi manipolare (ad esempio in maiuscolo) il testo dell&#8217;elemento emesso fornito in <code>$item-&gt;title<\/code>.<\/p>\n<h2>Fornire argomenti al tuo walker attraverso il tuo<code>wp_nav_menu<\/code><\/h2>\n<p>Vorrei citare un&#8217;altra cosa utile. Ricorda che $args contiene tutti gli argomenti forniti a <code>wp_nav_menu()<\/code>. Ci\u00f2 include ad esempio <code>theme_location<\/code>e altri, quindi se puoi modificare l&#8217;output solo per posizioni di temi specifici, ad esempio il menu principale. Ma puoi effettivamente fornire qualsiasi argomento personalizzato!<\/p>\n<p>Supponiamo che tu stia visualizzando lo stesso menu pi\u00f9 volte, ad esempio una per desktop e di nuovo per dispositivi mobili. Oppure vuoi che il tuo walker manipoli gli elementi solo quando vengono emessi <code>wp_nav_menu()<\/code>nel tuo tema e non quando il menu viene aggiunto tramite un widget? Forse vuoi che il tuo walker gestisca l&#8217;output in modo diverso in questi casi?<\/p>\n<p>Puoi fornire qualsiasi argomento personalizzato a <code>wp_nav_menu()<\/code>. Come semplice esempio, aggiunger\u00f2 un booleano &#8216; <code>show_carets<\/code>&#8216; agli argomenti per assicurarmi che i punti di inserimento vengano aggiunti solo nei casi in cui li voglio, invece della mia classe Walker che aggiunge i punti di inserimento a tutti i menu.<\/p>\n<pre><code>wp_nav_menu([\n    'theme_location' =&gt; 'primary',\n    'menu_class' =&gt; 'main-menu',\n    'container' =&gt; 'nav',\n    'container_class' =&gt; 'header__main-nav',\n    'walker' =&gt; new AWP_Menu_Walker(),\n    'show_carets' =&gt; true\n]);<\/code><\/pre>\n<p>Quindi posso semplicemente modificare il mio pezzo di codice con l&#8217;aggiunta di accento circonflesso sopra (riga n. 19-21) per verificare se <code>show_carets<\/code>\u00e8 presente o meno in <code>$args<\/code>, in questo modo:<\/p>\n<pre><code>if ($args-&gt;show_carets &amp;&amp; $args-&gt;walker-&gt;has_children) {\n    $output .= '&lt;i class=\"caret fa fa-angle-down\"&gt;&lt;\/i&gt;';\n}<\/code><\/pre>\n<p>Puoi aggiungere qualsiasi argomento desideri assicurandoti che il tuo walker personalizzi solo i menu che desideri. Ad esempio semplici booleani per casi diversi, ad esempio <code>is_mobile_menu<\/code>, o qualsiasi altra cosa di cui hai bisogno.<\/p>\n<p>E questo \u00e8 tutto. Sentiti libero di sperimentare e fammi sapere se hai domande o suggerimenti qui sotto!<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte di registrazione:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/awhitepixel.com\" class=\"external external_icon\">awhitepixel.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In questo post impareremo come creare, implementare e personalizzare la nostra classe walker per personalizzare l&#8217;output del nostro menu in WordPress.<\/p>\n","protected":false},"author":1,"featured_media":224083,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[918,896,896,918,1110,928,928,844,844,865,865],"tags":[1168],"class_list":["post-233913","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-altro","category-codice","category-n-a","category-soggetti","category-tutorial","category-wordpress-6","tag-affiai-it"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/posts\/233913","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/comments?post=233913"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/posts\/233913\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/media\/224083"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/media?parent=233913"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/categories?post=233913"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/it\/wp-json\/wp\/v2\/tags?post=233913"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}