WordPress 메뉴 항목에 필드 추가 – 사용자 정의 플러그인

게시 됨: 2021-05-19

이전 기사에서 WordPress 5.4에 도입된 wp_nav_menu_item_custom_fields 작업 후크를 사용하여 메뉴 항목에 사용자 정의 필드를 추가하는 방법을 살펴보았습니다. 이를 달성하기 위해 두 가지 경로를 자세히 설명했습니다. functions.php 에 사용자 정의 코드를 추가하거나 WordPress 플러그인을 사용합니다.

이 기사에서는 동일한 필드를 다시 만들지만 이번에는 처음부터 자체 플러그인을 만들어 수행합니다.

시작하자.

플러그인 생성

심층 기사 '첫 WordPress 플러그인을 빌드하는 방법'에서 다루었으므로 WordPress 플러그인 생성에 대한 기본 세부 정보는 다루지 않습니다. 단계별 가이드'. wp-content/plugin/ 폴더 아래에 플러그인 폴더를 만드는 단계로 건너뛰겠습니다. 다음으로 사용자 정의 플러그인 폴더의 이름을 "menu-item-field-creator"로 지정하고 그 안에 menu-item-field-creator.php 라는 파일을 생성합니다.

그런 다음 좋아하는 텍스트 편집기로 이 파일을 열고 아래 코드를 추가합니다. 이 코드는 플러그인을 WordPress 코어에 도입하는 효과가 있습니다.

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

아시다시피 플러그인 이름과 설명은 관리자 플러그인 영역에 표시되도록 정의했습니다. 이 예에서는 다른 헤더 필드를 정의하지 않습니다.

이 단계가 완료되면 관리 영역의 플러그인 섹션으로 이동하여 플러그인이 올바르게 표시되는지 확인하겠습니다.

다음으로, 메인 클래스와 일부 기능을 설정할 첫 번째 기능 코드를 삽입합니다.

간단한 방법

이 플러그인을 작동시키는 가장 간단한 방법은 이전 기사에서 작성한 코드를 플러그인의 기본 PHP 파일에 삽입하여 최종 내용이 다음과 같이 보이도록 하는 것입니다.

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

이 시점에서 플러그인을 활성화하면 제대로 작동하는 것을 확인할 수 있습니다. 그러나 다른 코딩 스타일을 사용하여 동일한 결과를 얻을 수 있는 방법이 있습니다.

객체 지향 프로그래밍 사용

관련 기사에서 설명한 대로 보다 객체 지향적인 접근 방식으로 동일한 결과를 얻으려면 아래 지침을 따르십시오.

시작하려면 헤더 주석을 제외하고 플러그인의 기본 PHP 파일 내용을 비우고 다음 행을 삽입하십시오.

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

지금까지 이 코드로 수행한 작업은 전체 기능을 포함할 MyCP_Menu_Item_Field_Creator 래퍼 클래스를 정의하는 것입니다. 마지막으로 객체를 인스턴스화합니다.

정의한 기본 클래스 이름은 전역적으로 사용 가능하므로 고유한지 확인하고 다른 플러그인이나 테마가 같은 이름을 사용할 가능성이 없다는 점을 기억하는 것이 매우 중요합니다. 그렇기 때문에 위에서 사용한 MyCP_ 와 같은 사용자 지정 접두사를 사용하는 것이 좋습니다.

클래스 내부에서 이제 몇 가지 기능을 추가할 것입니다. 플러그인 기본 PHP 파일의 최종 내용은 다음과 같습니다.

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

이제 클래스 접두사가 있으므로 메서드 이름에서 접두사를 제거했습니다.

__construct 함수에서 실행할 콜백 함수와 함께 사용한 후크를 정의했습니다. 다음으로 admin 사용자가 항목 부제목을 채울 수 있는 입력 필드를 표시하는 menu_item_sub 콜백 함수를 도입했습니다.

그런 다음 save_menu_item_sub 메소드를 사용하여 입력을 저장하고 마지막으로 show_menu_item_sub 콜백을 사용하여 가능한 경우 프런트 엔드 메뉴에 값을 표시합니다.

워커 확장

위의 예에서 메뉴 트리 데이터의 HTML 출력을 변경하지 않고 메뉴 항목 제목 안에 사용자 정의 메뉴 필드를 포함했습니다. 그러나 자막 필드를 제목 요소 링크 외부의 <div> 요소와 같은 별도의 HTML 요소로 추가하려면 어떻게 해야 할까요?

여기에서 Walker 클래스로 다시 한 번 작업해야 합니다. 'WordPress Walker 클래스에 익숙해지기' 기사에서 보았듯이 Walker를 확장하여 나무와 같은 데이터의 구조를 사용자 정의할 수 있습니다. 이 경우 메뉴가 됩니다.

이것은 물론 사용자 정의 필드의 프론트 엔드 디스플레이와 관련된 코드만 변경하면 된다는 것을 의미합니다. 이제 전체 코드를 다음 코드로 교체해 보겠습니다.

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

show_menu_item_sub 메소드를 삭제하고 프론트 엔드 메뉴 항목 구조를 다르게 작업했다는 것을 눈치채셨을 것입니다. 메인 클래스 외부에 커스텀 Walker 클래스 My_Custom_Nav_Walker 를 도입 menu_item_sub_custom_walker 메소드를 통해 'walker' 인수의 기본값을 My_Custom_Nav_Walker 로 변경했습니다. 이렇게 하면 사용자 정의 Walker에서 제공한 메뉴 HTML 출력이 프런트 엔드에 적용됩니다.

결과를 확인해보자.

우리가 볼 수 있듯이 이번에는 우리의 설명이 의도한 대로 메뉴 항목 링크의 href 외부에 배치됩니다.

더 나아가

마무리하기 전에 "자막" 예제를 사용하고 이해하기 쉽기 때문에 의도적으로 "자막" 예제를 사용했음을 언급할 가치가 있습니다.

자신을 밀어붙이고 싶다면 자신만의 시나리오를 만들어 실험해 볼 것을 제안합니다. 예를 들어 Admin 사용자가 메뉴 항목을 볼 수 있는 사용자 역할을 정의할 수 있는 다른 출력을 생성해 보십시오.

시작 힌트로 출력을 제공합니다. 현재 출력 방법 바꾸기(아래 참조)

 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 }

이것으로:

 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 }

이제 올바른 후크를 사용하여 현재/저장된 값을 표시하는 것과 함께 변경 사항을 저장하는 메서드를 생성해 보십시오.

결론

WordPress 메뉴를 사용자 정의하는 것은 이를 수행하는 데 사용할 수 있는 도구를 알게 될 때까지 답답할 수 있습니다. 이 기사가 달성할 수 있는 것과 이와 같은 작업을 구현하는 방법에 대한 통찰력을 제공했기를 바랍니다.

또한보십시오

  • WordPress 메뉴 항목에 사용자 정의 필드 추가