Tùy biến hiển thị menus trong wordpress – Nav Menu Walker

Quảng cáo
Ads_ngang
Website dinhthuanit.com có bài Tùy biến hiển thị menus trong wordpress – Nav Menu Walker

Nếu website của bạn có 1 hệ thống menu lớn, bạn mong muốn hiển thị phần nào dữ liệu menu ở một khu vực nào đó trên trang/ một trang khác. Bài viết này sẽ lý giải chi tiết việc làm này. Ý tưởng hiện ra trong đầu bạn là tạo từng menu cho mỗi trang, nhưng tại sao lại làm cách này chia nhỏ ra làm nhiều menus sẽ khó quản lý trong khi wordpress có API cho phép thiết lập tình trạng cho mỗi menu item.

Xóa ul wrap
Xóa ul bao menu chứa thẻ li, bạn điều chỉnh tham số ‘items_wrap’

    '%3$s' ) ); ?>   

Hoặc
Thêm ký tự trước menu

    'primary', 'items_wrap' =>  ' 
  • Menu:
  • %3$s
' ) ); ?>

Kế thừa Walker_Nav_Menu class

Tạo một class mới trong /functions.php , tên lớp nên có tiền tố để né trùng với class khác.

 class JC_Walker_Nav_Menu extends Walker_Nav_Menu { }  

Trong Class Walker_Nav_Menu có những hàm bạn có thể kế thừa và override, lớp được viết ở /wp-admin/includes/nav-menu.php
Ví dụ sau đây mình sẽ lấy tất cả menu items là con của 1 menu chỉ định, để làm điều ấy cần kế thừa 2 hàm của lớp là: start_llvl end_lvl .

 class JC_Walker_Nav_Menu extends Walker_Nav_Menu { function start_lvl( &$output, $depth = 0, $args = array() ) {} function end_lvl( &$output, $depth = 0, $args = array() ) {} }  

Truyền parent menu id vào construct để lấy xác định các menu item con, tiếp tục lấy các menu items ids con làm parent id để xác định các menu item con của nó, cứ thế cho tới hết, dùng mảng lưu mọi thứ các menu items cho chuyện quản lý.

 class JC_Walker_Nav_Menu extends Walker_Nav_Menu { var $menu_id = 0; var $menu_items = array(); function __construct($id = 0){ $this-> menu_id = $id; $this-> menu_items[] = $id; } function start_el( &$output, $item, $depth, $args ) { if( !empty($this-> menu_items) && !in_array($item-> ID, $this-> menu_items) && !in_array($item-> menu_item_parent, $this-> menu_items)){ return false; } if(!in_array($item-> ID, $this-> menu_items)){ $this-> menu_items[] = $item-> ID; } parent::start_el($output, $item, $depth, $args); } function end_el( &$output, $item, $depth = 0, $args = array() ) { if( !empty($this-> menu_items) && !in_array($item-> ID, $this-> menu_items) && !in_array($item-> menu_item_parent, $this-> menu_items)){ return false; } parent::end_el($output, $item, $depth, $args); } function start_lvl( &$output, $depth = 0, $args = array() ) {} function end_lvl( &$output, $depth = 0, $args = array() ) {} }  

Sử dụng Custom WordPress Walker

Hiển thị nav menu với wp_nav_menu , tái tạo class JC_Walker_Nav_Menu và truyền parent menu >

    'header-menu', 'walker' =>  new JC_Walker_Nav_Menu(8)) ); ?>   

Phương thức thừa hưởng trong class Walker

Bạn cũng đều có thể extends walker class để thay đổi nội dung hiển thị HTML cho item và thậm trí sub items tạo bởi các hàm như: wp_nav_menu , wp_list_pages , wp_list_categories .

Bằng cách sửa đổi nội dung của các hàm thiết kế của lớp kế thừa, chúng ta sẽ làm thay đổi cách hiển thị cho những dữ liệu Menu, Category trong wordpress.
Phương thức start_el mở thẻ li bắt đầu cho một item và tương ứng đóng item với phương thức end_el . Sử dụng tham số định vị thông tin và dữ liệu của item bạn cũng có thể có thể loại bỏ nó trong kết quả hiển thị. Ví dụ sau có loại bỏ top-level elements.

 // Don't print top-level elements function start_el(&$output, $item, $depth=0, $args=array()) { if( 0 == $depth ) return; parent::start_el(&$output, $item, $depth, $args); } function end_el(&$output, $item, $depth=0, $args=array()) { if( 0 == $depth ) return; parent::end_el(&$output, $item, $depth, $args); }  

Walker class còn có phương thức display_element , phương thức này giúp sử lý những item có chứa sub items bên dưới. Hàm display_element thừa hưởng trong class chính được chạy trong hàm start_el nếu có thừa kế tính năng của hàm mẹ start_el. Trong cách sử dụng php class, chúng ta gọi hàm mẹ của phương thức kế thừa với từ khóa parent, giống như thế này:

 // Don't print top-level elements function start_el(&$output, $item, $depth=0, $args=array()) { if( 0 == $depth ) return; parent::start_el(&$output, $item, $depth, $args); }  

Tham khảo mẫu nội dung đầy đủ của hàm start_el và end_el.

 var $number = 1; function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) { $indent = ( $depth ) ? str_repeat( "t", $depth ) : ''; $class_names = $value = ''; $classes = empty( $item-> classes ) ? array() : (array) $item-> classes; $classes[] = 'menu-item-' . $item-> ID; $class_names = join( ' ', apply_filters( 'nav_menu_css_ ' : ''; $id = apply_filters( 'nav_menu_item_menu-item-'. $item-> ID, $item, $args ); $id = $id ? ' > '; // add span with number here if ( $depth == 0 ) { // remove if statement if depth check is not required $output .= sprintf( '  %02s.  ', $this-> number++ ); } $atts = array(); $atts['title'] = ! empty( $item-> attr_title ) ? $item-> attr_title : ''; $atts['target'] = ! empty( $item-> target ) ? $item-> target : ''; $atts['rel'] = ! empty( $item-> xfn ) ? $item-> xfn : ''; $atts['href'] = ! empty( $item-> url ) ? $item-> url : ''; $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args ); $attributes = ''; foreach ( $atts as $attr =>  $value ) { if ( ! empty( $value ) ) { $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value ); $attributes .= ' ' . $attr . '="' . $value . '"'; } } $item_output = $args-> before; $item_output .= '  '; $item_output .= $args-> link_before . apply_filters( 'the_title', $item-> title, $item-> ID ) . $args-> link_after; $item_output .= ''; $item_output .= $args-> after; $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args ); } function end_el(&$output, $item, $depth=0, $args=array()) { $indent = ( $depth ) ? str_repeat( "t", $depth ) : ''; $output .= $indent."n"; }  

Mọi item đều sử lý qua hàm display_element này. Ví dụ, chúng ta không cho hiển thị các menu ở top-level và URL hiện tại không thuộc về item đó. Để làm điều này, chúng ta dựa vào thuộc tính class : current-menu-item, current-menu-parent, current-menu-ancestor

 // Only follow down one branch function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) { // Check if element as a 'current element' class $current_element_markers = array( 'current-menu-item', 'current-menu-parent', 'current-menu-ancestor' ); $current_class = array_intersect( $current_element_markers, $element-> classes ); // If element has a 'current' class, it is an ancestor of the current element $ancestor_of_current = !empty($current_class); // If this is a top-level link and not the current, or ancestor of the current menu item - stop here. if ( 0 == $depth && !$ancestor_of_current) return; parent::display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ); }  

Hai phương thức cuối cùng nhóm các sub items ở mọi levels, là start_lvl & end_lvl. Thường sử dụng thẻ ul. Nếu bạn cũng muốn loại bỏ cho nhóm items ở top-level. Lưu ý: toàn bộ những items trong level kia sẽ bỏ qua, chưa được hiển thị.

 // Don't wrap the top level function start_lvl(&$output, $depth=0, $args=array()) { if( 0 == $depth ) return; parent::start_lvl(&$output, $depth, $args); } function end_lvl(&$output, $depth=0, $args=array()) { if( 0 == $depth ) return; parent::end_lvl(&$output, $depth, $args); }  

Kế thừa nội dung của phương thức tạo thẻ bao items ở trên, đầy đặn giống như sau.

 function start_lvl(&$output, $depth=0, $args=array()) { $indent = ( $depth ) ? str_repeat( "t", $depth ) : ''; $output .= $indent."n 
    n"; } function end_lvl(&$output, $depth=0, $args=array()) { $indent = ( $depth ) ? str_repeat( "t", $depth ) : ''; $output .= $indent."
n"; }

Tùy biến hooks

Bạn để ý ngoài cách sử dụng class walker vào menu, bạn cũng có thể có thể chia nhỏ can thiệp vào từng dữ liệu có trong walker mặc định của menu với những hooks filter.

walker_nav_menu_start_el

Chúng ta để ý có filter ‘ walker_nav_menu_start_el ‘ cấp phép bạn tùy biến hiển thị menu bằng cách sửa hook này. Bạn cũng có thể có thể thêm vô functions.php như sau, ví dụ:

 if (function_exists('qtrans_convertURL')) { function qtrans_in_nav_el($output, $item, $depth, $args) { $attributes = !empty($item-> attr_title) ? ' title="' . esc_attr($item-> attr_title) . '"' : ''; $attributes .=!empty($item-> target) ? ' target="' . esc_attr($item-> target) . '"' : ''; $attributes .=!empty($item-> xfn) ? ' rel="' . esc_attr($item-> xfn) . '"' : ''; // Integration with qTranslate Plugin $attributes .=!empty($item-> url) ? ' href="' . esc_attr( qtrans_convertURL($item-> url) ) . '"' : ''; $output = $args-> before; $output .= '  '; $output .= $args-> link_before . apply_filters('the_title', $item-> title, $item-> ID) . $args-> link_after; $output .= ''; $output .= $args-> after; return $output; } add_filter('walker_nav_menu_start_el', 'qtrans_in_nav_el', 10, 4); }  

nav_menu_link_attributes

Bạn cũng có thể sửa mảng $atts là kết quả của filter nav_menu_link_attributes . Ví dụ sau mình fix lỗi URL trang chủ khi chuyển ngôn ngữ trong wordpress cho plugin qtranslate, bạn thêm đoạn code sau vào functions.php

 function qtrans_convertHomeURL($url, $what) { if($what=='/') return qtrans_convertURL($url); return $url; } add_filter('home_url', 'qtrans_convertHomeURL', 10, 2); add_filter('nav_menu_link_attributes','custom_menu',10,3); function custom_menu($atts, $item, $args){ if($item-> url=='/'){ $atts['href']=qtrans_convertURL($item-> url); } return $atts; }  

Sửa tham số wp_nav_menu

Bạn có thể sửa lại tham số cài đặt cho các menu tạo bởi wp_nav_menu , tùy chỉnh cấu hình của mọi menu sử dụng filter wp_nav_menu_args .

 function modify_nav_menu_args( $args ) { if( 'primary' == $args['theme_location'] ) { $args['depth'] = -1; $args['container_my_primary_menu'; } return $args; } add_filter( 'wp_nav_menu_args', 'modify_nav_menu_args' );  

Khi wp_nav_menu lấy giá trị mảng truyền vào, nó sẽ sử lý qua filter wp_nav_menu_args, do đấy chúng ta có thể sửa lại mọi menu trước lúc nó được hiển thị như đúng thiết lập tại địa thế gọi hàm hiển thị menu wp_nav_menu .

Tạo Custom Menu Widget

Tạo custom menu widget, cho chọn lựa hiển thị một phần của menu. Xem code widget sau đây:

    __( 'Custom options to output menus in your theme')) // Args ); } public function widget( $args, $instance ) { extract( $args ); $title = apply_filters( 'widget_title', $instance['title'] ); echo $before_widget; if ( ! empty( $title ) ) echo $before_title . $title . $after_title; wp_nav_menu( array('menu' =>  $instance['menu'], 'walker' =>  new JC_Walker_Nav_Menu($instance['menu_item'])) ); echo $after_widget; } public function form( $instance ) { $title = isset($instance['title']) ? $instance['title'] : ''; $menu = isset($instance['menu']) ? $instance['menu'] : ''; $menu_item = isset($instance['menu_item']) ? $instance['menu_item'] : ''; $menus = get_terms('nav_menu'); ?>   

<label for=" get_field_id( 'title' ); ?> "> get_field_id( 'title' ); ?> " name=" get_field_name( 'title' ); ?> " type="text" value=" " />

get_field_id( 'menu' ); ?> " name=" get_field_name( 'menu' ); ?> " type="hidden" value=" " />

<label for=" get_field_id( 'menu_item' ); ?> "> get_field_id( 'menu_item' ); ?> " name=" get_field_name( 'menu_item' ); ?> " > $m-> slug, // your theme location here 'container' => false, 'walker' => new Walker_Nav_Menu_Dropdown($menu_item), 'items_wrap' => ' slug.'" label="'.$m-> name.'"> %3$s ', )); } ?>

item_id = $id; } public function start_lvl(&$output, $depth){} public function end_lvl(&$output, $depth){} public function start_el(&$output, $item, $depth, $args){ $item-> title = str_repeat(" ", $depth * 4) . $item-> title; parent::start_el($output, $item, $depth, $args); if($item-> ID == $this-> item_id) $output = str_replace(' <li', ' ID.'" selected="selected"', $output); else $output = str_replace(' <li', ' ID.'"', $output); } public function end_el(&$output, $item, $depth){ $output .= " n"; } } ?>

Ngoài tính năng walker mà menu cung cấp, cũng có thể có thể sử dụng các hàm menu : wp_get_nav_menu_items, wp_get_nav_menu_object, get_nav_menu_locations..
để lấy dữ liệu menu.
Tham khảo:

 function vcn_menus_items($id){ static $data_menu=array(); $locations = get_nav_menu_locations(); $menu=wp_get_nav_menu_object($locations['menu1']); $args=array( "post_parent"=> $id //'post_type'=> 'nav_menu_item', //'post_parent'=> 0 ); $menu_items = wp_get_nav_menu_items($menu-> term_id,$args); if(count($data_menu)==0) foreach( (array)$menu_items as $key=> $menu_item){print_r($menu_item); $t = wp_get_nav_menu_items($menu_item-> object_id,array('post_parent'=> $menu_item-> post_parent));print_r($t); echo ' 
';continue; echo $menu_item-> post_type.'
'; echo $menu_item-> object.'
'; echo $menu_item-> url.'
'; echo $menu_item-> menu_item_parent .'
'; echo $menu_item-> title.'
'; //các item theo thứ tự or trong cùng 1 menu item gốc:ie: /* -item 1 //theo thứ tự: ie (1) -item-1-0 (2) -item-1-1 (3) -item-1-2 (4) ... -item 2 //khác menu_order ie:(6) */ $element-> menu_order //save if(!$menu_item-> menu_item_parent) $data_menu[]=array('main'=> $menu_item,'sub'=> array()); else $data_menu[count($data_menu)-1]['sub'][]=$menu_item; //echo '
  • ' . $title . '
  • '; } return $data_menu; }

    Hết !

    Hãy cho mình biết suy nghĩ của bạn trong phần bình luận bên dưới bài viết này. Hãy theo dấu kênh chia sẻ kiến thức WordPress của TopVn trên Twitter và Facebook

    Bài viết Tùy biến hiển thị menus trong wordpress – Nav Menu Walker được tổng hợp và biên tập bởi: dinhthuanit.com. Mọi ý kiến đóng góp và phản hồi vui lòng gửi Liên Hệ cho dinhthuanit.com để điều chỉnh. dinhthuanit.com xin cảm ơn.

    Bài Viết Liên Quan


    Bài Viết Khác


    Quảng cáo
    Ads_ngang