Aggiunta di campi alle voci di menu di WordPress – Plugin personalizzato

Pubblicato: 2021-05-19

In un articolo precedente abbiamo esaminato come aggiungere il proprio campo personalizzato alle voci di menu utilizzando l'action hook wp_nav_menu_item_custom_fields introdotto in WordPress 5.4. Abbiamo dettagliato due percorsi per raggiungere questo obiettivo; aggiungendo del codice personalizzato a functions.php o utilizzando un plugin per WordPress.

In questo articolo ricreeremo lo stesso campo ma questa volta lo faremo creando il nostro plugin da zero.

Iniziamo.

Creazione plugin

Non entreremo nei dettagli di base della creazione di un plugin per WordPress poiché questo è stato trattato nel nostro articolo approfondito "Come creare il tuo primo plugin per WordPress. Una guida passo passo'. Passeremo alla creazione della nostra cartella dei plugin nella cartella wp-content/plugin/ . Successivamente chiameremo la nostra cartella del plugin personalizzato "menu-item-field-creator" e al suo interno creeremo un file chiamato menu-item-field-creator.php .

Dopo questo apriremo questo file con il nostro editor di testo preferito e aggiungeremo il codice qui sotto. Questo codice ha l'effetto di introdurre il plugin nel core di WordPress.

 <?php /* Plugin Name: Menu Item Field Creator Description: My custom plugin to create menu item fields */

Come puoi notare, abbiamo definito il nome e la descrizione del plug-in perché desideriamo che vengano visualizzati nell'area del plug-in di amministrazione. Per il bene di questo esempio non definiremo nessun altro campo di intestazione.

Dopo aver completato questi passaggi, andiamo alla nostra sezione Plugin nell'area Admin e controlliamo se il plug-in è mostrato correttamente.

Successivamente, inseriremo il nostro primo codice funzionale che stabilirà la nostra classe principale e alcune funzioni.

Il modo semplice

Il modo più semplice per far funzionare questo plugin è inserire il codice che abbiamo scritto nel nostro articolo precedente nel file PHP principale del plugin in modo che il contenuto finale assomigli a questo:

 <?php /* Plugin Name: Menu Item Field Creator Description: My custom plugin to create menu item fields */ /** * Add the field. */ function pr_menu_item_sub( $item_id, $item ) { $menu_item_sub = get_post_meta( $item_id, '_menu_item_sub', true ); ?> <div> <span class="subtitle"><?php _e( 'Subtitle', 'menu-item-sub' ); ?></span><br /> <input type="hidden" class="nav-menu-id" value="<?php echo $item_id; ?>" /> <div class="logged-input-holder"> <input type="text" name="menu_item_sub[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $menu_item_sub ); ?>" /> </div> </div> <?php } add_action( 'wp_nav_menu_item_custom_fields', 'pr_menu_item_sub', 10, 2 ); /** * Save input. */ function save_menu_item_sub( $menu_id, $menu_item_db_id ) { if ( isset( $_POST['menu_item_sub'][ $menu_item_db_id ] ) ) { $sanitized_data = sanitize_text_field( $_POST['menu_item_sub'][ $menu_item_db_id ] ); update_post_meta( $menu_item_db_id, '_menu_item_sub', $sanitized_data ); } else { delete_post_meta( $menu_item_db_id, '_menu_item_sub' ); } } add_action( 'wp_update_nav_menu_item', 'save_menu_item_sub', 10, 2 ); /** * Show the Menu Field Value. */ function show_menu_item_sub( $title, $item ) { if ( is_object( $item ) && isset( $item->ID ) ) { $menu_item_sub = get_post_meta( $item->ID, '_menu_item_sub', true ); if ( ! empty( $menu_item_sub ) ) { $title .= '<p class="menu-item-sub">' . $menu_item_sub . '</p>'; } } return $title; } add_filter( 'nav_menu_item_title', 'show_menu_item_sub', 10, 2 );

A questo punto, se attivi il plugin dovresti scoprire che funziona bene. Esiste tuttavia un modo per ottenere gli stessi risultati utilizzando uno stile di codifica diverso.

Utilizzo della programmazione orientata agli oggetti

Per ottenere gli stessi risultati in un approccio più orientato agli oggetti, come descritto nel nostro articolo correlato, seguire le istruzioni seguenti.

Per iniziare, svuota il contenuto del file PHP principale del tuo plugin, ad eccezione del commento dell'intestazione e inserisci queste righe:

 class MyCP_Menu_Item_Field_Creator { } $mycp_menu_item_field_creator = new MyCP_Menu_Item_Field_Creator();

Quello che abbiamo fatto finora con questo codice è definire la classe wrapper MyCP_Menu_Item_Field_Creator che conterrà l'intera funzionalità. Infine, istanziamo un oggetto.

È molto importante ricordare che il nome della classe principale che definisci sarà disponibile a livello globale e quindi devi assicurarti che sia univoco e che non ci siano possibilità che altri plugin o temi utilizzino lo stesso nome. Ecco perché si consiglia di utilizzare un prefisso personalizzato come MyCP_ che abbiamo usato sopra.

All'interno della classe aggiungeremo ora alcune funzionalità. Il contenuto finale del nostro file PHP principale del plugin sarà simile a questo:

 <?php /* Plugin Name: Menu Item Field Creator Description: My custom plugin to create menu item fields */ class MyCP_Menu_Item_Field_Creator { public function __construct() { add_action( 'wp_nav_menu_item_custom_fields', array( $this, 'menu_item_sub' ), 10, 2 ); add_action( 'wp_update_nav_menu_item', array( $this, 'save_menu_item_sub' ), 10, 2 ); add_action( 'nav_menu_item_title', array( $this, 'show_menu_item_sub' ), 10, 2 ); } public function menu_item_sub( $item_id, $item ) { $menu_item_sub = get_post_meta( $item_id, '_menu_item_sub', true ); ?> <div> <span class="subtitle"><?php _e( 'Subtitle', 'menu-item-sub' ); ?></span><br /> <input type="hidden" class="nav-menu-id" value="<?php echo $item_id; ?>" /> <div class="logged-input-holder"> <input type="text" name="menu_item_sub[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $menu_item_sub ); ?>" /> </div> </div> <?php } public function save_menu_item_sub( $menu_id, $menu_item_db_id ) { if ( isset( $_POST['menu_item_sub'][ $menu_item_db_id ] ) ) { $sanitized_data = sanitize_text_field( $_POST['menu_item_sub'][ $menu_item_db_id ] ); update_post_meta( $menu_item_db_id, '_menu_item_sub', $sanitized_data ); } else { delete_post_meta( $menu_item_db_id, '_menu_item_sub' ); } } public function show_menu_item_sub( $title, $item ) { if ( is_object( $item ) && isset( $item->ID ) ) { $menu_item_sub = get_post_meta( $item->ID, '_menu_item_sub', true ); if ( ! empty( $menu_item_sub ) ) { $title .= '<p class="menu-item-sub">' . $menu_item_sub . '</p>'; } } return $title; } } $mycp_menu_item_field_creator = new MyCP_Menu_Item_Field_Creator();

Abbiamo rimosso i prefissi dai nomi dei metodi poiché ora abbiamo invece un prefisso di classe.

Nella funzione __construct abbiamo definito gli hook che abbiamo usato insieme alle loro funzioni di callback che verranno eseguite. Successivamente abbiamo introdotto la funzione di callback menu_item_sub che mostrerà il campo di input in cui l'utente amministratore può compilare il sottotitolo dell'elemento.

Successivamente, salviamo l'input con il metodo save_menu_item_sub e infine, con il callback show_menu_item_sub , mostriamo i valori, se disponibili, nel menu front-end.

Espandere il Walker

Nell'esempio sopra abbiamo incluso il campo del menu personalizzato all'interno del titolo della voce di menu, senza alterare l'output HTML dei dati dell'albero del menu. Ma cosa succede se volessimo aggiungere il campo dei sottotitoli come un elemento HTML separato come un elemento <div> al di fuori del collegamento dell'elemento del titolo?

È qui che dobbiamo lavorare ancora una volta con la classe Walker. Come abbiamo visto nel nostro articolo 'Imparare a familiarizzare con la WordPress Walker Class', estendendo il Walker è possibile personalizzare la struttura di dati ad albero. In questo caso questo sarà il menu.

Ciò significa ovviamente che dobbiamo solo modificare il nostro codice relativo alla visualizzazione front-end del nostro campo personalizzato. Quindi andiamo a sostituire l'intero codice con questo:

 <?php /* Plugin Name: Menu Item Field Creator Description: My custom plugin to create menu item fields */ class MyCP_Menu_Item_Field_Creator { public function __construct() { add_action( 'wp_nav_menu_item_custom_fields', array( $this, 'menu_item_sub' ), 10, 2 ); add_action( 'wp_update_nav_menu_item', array( $this, 'save_menu_item_sub' ), 10, 2 ); add_filter( 'wp_nav_menu_args', array( $this, 'menu_item_sub_custom_walker' ) ); } public function menu_item_sub( $item_id, $item ) { $menu_item_sub = get_post_meta( $item_id, '_menu_item_sub', true ); ?> <div> <span class="subtitle"><?php _e( 'Subtitle', 'menu-item-sub' ); ?></span><br /> <input type="hidden" class="nav-menu-id" value="<?php echo $item_id; ?>" /> <div class="logged-input-holder"> <input type="text" name="menu_item_sub[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $menu_item_sub ); ?>" /> </div> </div> <?php } public function save_menu_item_sub( $menu_id, $menu_item_db_id ) { if ( isset( $_POST['menu_item_sub'][ $menu_item_db_id ] ) ) { $sanitized_data = sanitize_text_field( $_POST['menu_item_sub'][ $menu_item_db_id ] ); update_post_meta( $menu_item_db_id, '_menu_item_sub', $sanitized_data ); } else { delete_post_meta( $menu_item_db_id, '_menu_item_sub' ); } } public function menu_item_sub_custom_walker( $args ) { if ( class_exists( 'My_Custom_Nav_Walker' ) ) { $args['walker'] = new My_Custom_Nav_Walker(); } else { echo 'DOES NOT EXIST'; } return $args; } } $mycp_menu_item_field_creator = new MyCP_Menu_Item_Field_Creator(); if ( ! class_exists( 'My_Custom_Nav_Walker' ) ) { class My_Custom_Nav_Walker extends Walker_Nav_Menu { public function start_el( &$output, $item, $depth=0, $args=[], $id=0 ) { $menu_item_sub = get_post_meta( $item->ID, '_menu_item_sub', true ); $output .= '<li class="' . implode( ' ', $item->classes ) . '">'; if ( $item->url && $item->url != '#' ) { $output .= '<a href="' . $item->url . '">'; } else { $output .= '<span>'; } $output .= $item->title; if ( $item->url && $item->url != '#' ) { $output .= '</a>'; } else { $output .= '</span>'; } if ( ! empty( $menu_item_sub ) ) { $output .= '<div class="menu-item-sub">' . $menu_item_sub . '</div>'; } } } }

Potresti aver notato che abbiamo eliminato il metodo show_menu_item_sub e lavorato con la struttura delle voci di menu front-end in modo diverso. Abbiamo introdotto la nostra classe Walker personalizzata My_Custom_Nav_Walker al di fuori della nostra classe principale e tramite il nostro metodo menu_item_sub_custom_walker abbiamo modificato il valore predefinito per l'argomento 'walker' in My_Custom_Nav_Walker . In questo modo l'output HTML del menu che abbiamo fornito nel nostro Walker personalizzato verrà applicato al nostro front-end.

Controlliamo i risultati.

Come possiamo vedere, la nostra descrizione questa volta è collocata al di fuori dell'href del collegamento alla voce di menu come previsto.

Portarlo oltre

Prima di concludere, vale la pena ricordare che abbiamo usato deliberatamente l'esempio "Sottotitoli" perché è semplice da fare e da capire.

Se vuoi metterti alla prova, ti consigliamo di creare i tuoi scenari con cui sperimentare. Provare ad esempio a creare un output diverso che consenta all'utente Admin di definire quale ruolo utente è autorizzato a visualizzare la voce di menu.

Come suggerimento di partenza, ti forniremo l'output. Sostituisci il metodo di output corrente (mostrato di seguito)

 function menu_item_sub( $item_id, $item ) { $menu_item_sub = get_post_meta( $item_id, '_menu_item_sub', true ); ?> <div> <span class="subtitle"><?php _e( 'Subtitle', 'menu-item-sub' ); ?></span><br /> <input type="hidden" class="nav-menu-id" value="<?php echo $item_id; ?>" /> <div class="logged-input-holder"> <input type="text" name="menu_item_sub[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $menu_item_sub ); ?>" /> </div> </div> <?php }

con questo:

 function PREFIX_Menu_Item_Roles() { global $wp_roles; $display_roles = apply_filters( 'nav_menu_roles', $wp_roles->role_names ); if ( ! $display_roles ) return; ?> <p class="field-nav_menu_logged_in_out nav_menu_logged_in_out nav_menu_logged_in_out-thin"> <fieldset> <legend><?php _e( 'Display Mode', 'nav-menu-roles' ); ?></legend> <label for="edit-menu-item-role_logged_in"> <input type="radio" class="edit-menu-item-logged_in_out" value="in" name="menu-item-role_logged_in" /> <?php _e( 'Logged In Users', 'nav-menu-roles' ); ?><br/> </label> <label for="edit-menu-item-role_logged_out"> <input type="radio" class="edit-menu-item-logged_in_out" value="out" name="menu-item-role_logged_out" /> <?php _e( 'Logged Out Users', 'nav-menu-roles' ); ?><br/> </label> <label for="edit-menu-item-role_everyone"> <input type="radio" class="edit-menu-item-logged_in_out" value="" name="menu-item-role_everyone" /> <?php _e( 'Everyone', 'nav-menu-roles' ); ?><br/> </label> </fieldset> </p> <?php }

Ora prova a creare un metodo che salvi le modifiche insieme a uno che mostri il valore corrente/salvato usando gli hook corretti.

Conclusione

La personalizzazione di un menu di WordPress può essere frustrante finché non vieni informato degli strumenti a tua disposizione per farlo. Si spera che questo articolo ti abbia fornito alcune informazioni su ciò che è possibile ottenere e sui modi in cui puoi implementare attività come questa.

Guarda anche

  • Aggiunta di campi personalizzati alle voci di menu di WordPress