Adăugarea de câmpuri la elementele de meniu WordPress – Plugin personalizat

Publicat: 2021-05-19

Într-un articol anterior, am analizat cum puteți adăuga propriul câmp personalizat la elementele de meniu folosind cârligul de acțiune wp_nav_menu_item_custom_fields care a fost introdus în WordPress 5.4. Am detaliat două rute pentru a realiza acest lucru; prin adăugarea unui cod personalizat la functions.php sau prin utilizarea unui plugin WordPress.

În acest articol, vom recrea același câmp, dar de data aceasta o vom face creând propriul nostru plugin de la zero.

Să începem.

Creare plugin

Nu vom intra în detaliile de bază ale creării unui plugin WordPress, deoarece acest lucru a fost tratat în articolul nostru detaliat „Cum să construiți primul dvs. plugin WordPress. Un ghid pas cu pas'. Vom trece mai departe la crearea folderului nostru cu pluginuri în folderul wp-content/plugin/ . În continuare, vom denumi folderul plugin-ului personalizat „menu-item-field-creator” și în interiorul acestuia vom crea un fișier numit menu-item-field-creator.php .

După aceasta, vom deschide acest fișier cu editorul nostru de text preferat și vom adăuga codul de mai jos. Acest cod are ca efect introducerea pluginului în nucleul WordPress.

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

După cum puteți observa, am definit numele și descrierea pluginului, deoarece dorim ca acestea să fie afișate în zona pluginului de administrare. De dragul acestui exemplu, nu vom defini niciun alt câmp de antet.

Cu acești pași finalizați, să ne îndreptăm către secțiunea Plugin-uri din zona Admin și să verificăm dacă pluginul este afișat corect.

În continuare, vom introduce primul nostru cod funcțional care va stabili clasa noastră principală și unele funcții.

Calea Simplă

Cel mai simplu mod de a face acest plugin să funcționeze este să inserați codul pe care l-am scris în articolul nostru anterior în fișierul PHP principal al pluginului, astfel încât conținutul final să arate astfel:

 <?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 );

În acest moment, dacă activați pluginul, ar trebui să găsiți că funcționează bine. Există totuși o modalitate de a obține aceleași rezultate folosind un stil de codare diferit.

Utilizarea programarii orientate pe obiecte

Pentru a obține aceleași rezultate într-o abordare mai orientată pe obiecte, așa cum am descris-o în articolul nostru asociat, vă rugăm să urmați instrucțiunile de mai jos.

Pentru a începe, goliți conținutul fișierului PHP principal al pluginului dvs., cu excepția comentariului din antet și introduceți aceste rânduri:

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

Ceea ce am făcut cu acest cod până acum este să definim clasa de wrapper MyCP_Menu_Item_Field_Creator care va conține întreaga funcționalitate. În cele din urmă, instanțiem un obiect.

Este foarte important să rețineți că numele clasei principale pe care îl definiți va fi disponibil la nivel global și, prin urmare, trebuie să vă asigurați că este unic și că nu există nicio șansă ca vreun alt plugin sau temă să folosească același nume. De aceea, este recomandat să utilizați un prefix personalizat, cum ar fi MyCP_ pe care l-am folosit mai sus.

În cadrul clasei vom adăuga acum câteva funcționalități. Conținutul final al fișierului PHP principal al pluginului va arăta astfel:

 <?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();

Am eliminat prefixele din numele metodelor, deoarece acum avem un prefix de clasă.

În funcția __construct am definit cârligele pe care le-am folosit împreună cu funcțiile lor de apel invers care se vor executa. În continuare am introdus funcția de apel invers menu_item_sub care va afișa câmpul de introducere în care utilizatorul administrator poate completa subtitrarea articolului.

După aceasta, salvăm intrarea cu metoda save_menu_item_sub și în final, cu callback-ul show_menu_item_sub , arătăm valorile, dacă sunt disponibile, în meniul front-end.

Extinderea Walker-ului

În exemplul de mai sus am inclus câmpul de meniu personalizat în interiorul titlului elementului de meniu, fără a modifica rezultatul HTML al datelor din arborele de meniu. Dar ce se întâmplă dacă am dori să adăugăm câmpul de subtitrare ca element HTML separat, cum ar fi un element <div> în afara linkului elementului titlu?

Aici trebuie să lucrăm din nou cu clasa Walker. După cum am văzut în articolul nostru „ Familiarizarea cu clasa WordPress Walker”, prin extinderea Walker-ului puteți personaliza structura unei date de tip arbore. În acest caz, acesta va fi meniul.

Aceasta înseamnă, desigur, că trebuie doar să ne modificăm codul legat de afișarea front-end a câmpului nostru personalizat. Deci haideți să înlocuim întregul cod cu acesta:

 <?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>'; } } } }

Poate ați observat că am șters metoda show_menu_item_sub și am lucrat diferit cu structura elementului de meniu frontal. Am introdus clasa noastră personalizată Walker My_Custom_Nav_Walker în afara clasei noastre principale și prin metoda menu_item_sub_custom_walker am schimbat valoarea implicită pentru argumentul „walker” în My_Custom_Nav_Walker . În acest fel, rezultatul HTML al meniului pe care l-am furnizat în Walker-ul nostru personalizat se va aplica în front-end-ul nostru.

Să verificăm rezultatele.

După cum putem vedea, descrierea noastră de această dată este plasată în afara linkului href al elementului de meniu, așa cum ne-am propus.

Ducând-o mai departe

Înainte de a încheia acest lucru, merită menționat că am folosit în mod deliberat exemplul „Subtitrare”, deoarece este simplu de făcut și de înțeles.

Dacă doriți să vă împingeți, vă recomandăm să vă creați propriile scenarii pe care să le experimentați. Încercați, de exemplu, să creați o ieșire diferită care să permită utilizatorului administrator să definească ce rol de utilizator are permisiunea de a vizualiza elementul de meniu.

Ca un indiciu de pornire, vă vom oferi rezultatul. Înlocuiți metoda de ieșire curentă (prezentată mai jos)

 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 }

Cu acesta:

 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 }

Acum încercați să creați o metodă care salvează modificările împreună cu una care afișează valoarea curentă/salvată folosind cârligele corecte.

Concluzie

Personalizarea unui meniu WordPress poate fi frustrantă până când sunteți conștient de instrumentele disponibile pentru a face acest lucru. Sperăm că acest articol v-a oferit câteva informații despre ceea ce este posibil de realizat și despre modalitățile prin care puteți implementa sarcini ca aceasta.

Vezi si

  • Adăugarea de câmpuri personalizate la elementele de meniu WordPress