Dodawanie pól do pozycji menu WordPress – wtyczka niestandardowa

Opublikowany: 2021-05-19

W poprzednim artykule przyjrzeliśmy się, jak dodać własne niestandardowe pole do elementów menu za pomocą haka akcji wp_nav_menu_item_custom_fields , który został wprowadzony w WordPress 5.4. Wyszczególniliśmy dwie drogi, aby to osiągnąć; dodając niestandardowy kod do functions.php lub używając wtyczki WordPress.

W tym artykule odtworzymy to samo pole, ale tym razem zrobimy to tworząc od podstaw własną wtyczkę.

Zacznijmy.

Tworzenie wtyczki

Nie będziemy wchodzić w podstawowe szczegóły tworzenia wtyczki WordPress, ponieważ zostało to omówione w naszym szczegółowym artykule „Jak zbudować swoją pierwszą wtyczkę WordPress. Przewodnik krok po kroku”. Przeskoczymy do tworzenia naszego folderu wtyczek w folderze wp-content/plugin/ . Następnie nazwiemy nasz niestandardowy folder wtyczek „menu-item-field-creator”, a wewnątrz niego utworzymy plik o nazwie menu-item-field-creator.php .

Następnie otworzymy ten plik w naszym ulubionym edytorze tekstu i dodamy poniższy kod. Ten kod powoduje wprowadzenie wtyczki do rdzenia WordPressa.

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

Jak możesz zauważyć, zdefiniowaliśmy nazwę i opis wtyczki, ponieważ chcemy, aby były wyświetlane w obszarze wtyczek administratora. Na potrzeby tego przykładu nie będziemy definiować żadnego innego pola nagłówka.

Po wykonaniu tych kroków przejdźmy do naszej sekcji Wtyczki w obszarze administracyjnym i sprawdź, czy wtyczka jest poprawnie wyświetlana.

Następnie wstawimy nasz pierwszy kod funkcjonalny, który ustanowi naszą główną klasę i niektóre funkcje.

Prosty sposób

Najprostszym sposobem na uruchomienie tej wtyczki jest wstawienie kodu, który napisaliśmy w naszym poprzednim artykule do głównego pliku PHP wtyczki, tak aby ostateczna zawartość wyglądała tak:

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

W tym momencie, jeśli aktywujesz wtyczkę, powinieneś stwierdzić, że działa dobrze. Istnieje jednak sposób na osiągnięcie tych samych wyników przy użyciu innego stylu kodowania.

Korzystanie z programowania obiektowego

Aby osiągnąć te same wyniki w podejściu bardziej zorientowanym obiektowo, jak opisaliśmy to w naszym powiązanym artykule, postępuj zgodnie z poniższymi instrukcjami.

Aby rozpocząć, opróżnij zawartość głównego pliku PHP wtyczki, z wyjątkiem komentarza nagłówka i wstaw następujące wiersze:

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

To, co do tej pory zrobiliśmy z tym kodem, to zdefiniowanie klasy wrappera MyCP_Menu_Item_Field_Creator , która będzie zawierała całą funkcjonalność. Na koniec tworzymy instancję obiektu.

Bardzo ważne jest, aby pamiętać, że główna nazwa klasy, którą definiujesz, będzie dostępna globalnie i dlatego musisz upewnić się, że jest unikalna i że nie ma szans, aby jakakolwiek inna wtyczka lub motyw używała tej samej nazwy. Dlatego zaleca się użycie niestandardowego prefiksu, takiego jak MyCP_ , którego użyliśmy powyżej.

Wewnątrz klasy dodamy teraz pewną funkcjonalność. Ostateczna zawartość głównego pliku PHP naszej wtyczki będzie wyglądać tak:

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

Usunęliśmy przedrostki z nazw metod, ponieważ mamy teraz przedrostek klas.

W funkcji __construct zdefiniowaliśmy haki, których użyliśmy wraz z ich funkcjami zwrotnymi, które zostaną wykonane. Następnie wprowadziliśmy funkcję zwrotną menu_item_sub , która wyświetli pole wejściowe, w którym administrator może wypełnić podtytuł pozycji.

Następnie zapisujemy dane wejściowe za pomocą metody save_menu_item_sub , a na koniec, za pomocą wywołania zwrotnego show_menu_item_sub , wyświetlamy wartości, jeśli są dostępne, w menu interfejsu użytkownika.

Rozszerzanie Walkera

W powyższym przykładzie umieściliśmy niestandardowe pole menu wewnątrz tytułu pozycji menu, bez zmiany wyniku HTML danych drzewa menu. Ale co by było, gdybyśmy chcieli dodać pole napisów jako oddzielny element HTML, taki jak element <div> poza łączem do elementu title?

W tym miejscu musimy ponownie popracować z klasą Walkera. Jak widzieliśmy w naszym artykule „Poznawanie klasy WordPress Walker”, rozszerzając Walker, możesz dostosować strukturę danych przypominających drzewo. W tym przypadku będzie to menu.

Oznacza to oczywiście, że musimy tylko zmienić nasz kod związany z wyświetlaniem naszego niestandardowego pola na froncie. Więc chodźmy i zamieńmy cały kod na ten:

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

Być może zauważyłeś, że usunęliśmy metodę show_menu_item_sub i inaczej pracowaliśmy ze strukturą elementów menu front-end. Wprowadziliśmy naszą niestandardową klasę Walker My_Custom_Nav_Walker poza naszą główną klasą i za pomocą naszej metody menu_item_sub_custom_walker zmieniliśmy domyślną wartość argumentu „walker” na My_Custom_Nav_Walker . W ten sposób wyjście HTML menu, które dostarczyliśmy w naszym niestandardowym Walkerze, zostanie zastosowane w naszym interfejsie.

Sprawdźmy wyniki.

Jak widzimy, nasz opis tym razem jest umieszczony poza hrefem linku do pozycji menu, zgodnie z naszymi zamierzeniami.

Idąc dalej

Zanim to zakończymy, warto wspomnieć, że celowo użyliśmy przykładu „Podtytuł”, ponieważ jest prosty do wykonania i zrozumienia.

Jeśli chcesz się popchnąć, sugerujemy stworzenie własnych scenariuszy do eksperymentowania. Spróbuj na przykład utworzyć inne dane wyjściowe, które pozwolą administratorowi określić, która rola użytkownika może wyświetlać dany element menu.

Jako wskazówkę na początek przedstawimy Ci wyniki. Zastąp bieżącą metodę wyjściową (pokazaną poniżej)

 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 }

z tym:

 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 }

Teraz spróbuj stworzyć metodę, która zapisuje zmiany wraz z taką, która wyświetla bieżącą/zapisaną wartość przy użyciu odpowiednich hooków.

Wniosek

Dostosowywanie menu WordPress może być frustrujące, dopóki nie zostaniesz poinformowany o dostępnych narzędziach, aby to zrobić. Mam nadzieję, że ten artykuł dał ci pewne informacje na temat tego, co można osiągnąć i sposobów, w jakie możesz wykonać takie zadania.

Zobacz też

  • Dodawanie niestandardowych pól do pozycji menu WordPress