ทำความคุ้นเคยกับ WordPress Walker Class

เผยแพร่แล้ว: 2020-11-27

หากคุณไม่คุ้นเคยกับ Walker Class ให้เตรียมพร้อมที่จะทึ่งกับประโยชน์ที่ได้รับสำหรับงานของคุณ คลาส WordPress Walker ถูกนำมาใช้ใน WordPress 2.1 เพื่อให้นักพัฒนามีวิธีสำรวจโครงสร้างข้อมูลที่เหมือนต้นไม้เพื่อวัตถุประสงค์ในการแสดง HTML ในบทความนี้ เราจะศึกษาวิธีการทำงานของพารามิเตอร์ walker และวิธีปรับแต่งผลลัพธ์ในเมนู หมวดหมู่ และความคิดเห็น

เริ่มกันเลย!

ภาพรวมคลาสวอล์คเกอร์

ใน WordPress เรามักจะเห็นวัตถุที่มีโครงสร้างแบบลำดับชั้น เช่น เมนูนำทาง รายการหมวดหมู่ หรือรายการความคิดเห็น

อย่างที่คุณอาจทราบแล้ว ในกรณีของโครงสร้างข้อมูลแบบต้นไม้ องค์ประกอบบางอย่างคือพ่อแม่ และองค์ประกอบอื่นๆ คือลูกขององค์ประกอบเหล่านั้น “Post Subcategory 1” เป็นรายการย่อยของ “Post Category 1” การตอบกลับความคิดเห็นคือความคิดเห็นย่อยของความคิดเห็นนั้นเอง และ “Service 1” เป็นรายการเมนูย่อยของรายการ “Services”

Walker ได้รับการตั้งชื่อว่า "เดิน" ผ่านแต่ละวัตถุหรืออาร์เรย์ที่เชื่อมโยงและดำเนินการฟังก์ชันที่แต่ละโหนด สิ่งที่เราต้องการทำให้สำเร็จคือความสามารถในการแสดงรายการลิงก์ 'ระดับบนสุด' โดยมีรายการ 'ย่อย' ในรูปแบบต่างๆ ตามความต้องการเฉพาะของเรา

กล่าวอีกนัยหนึ่ง WordPress ให้โครงสร้าง <ul> <li> มาตรฐาน และคุณสามารถปรับแต่งอาร์กิวเมนต์ได้ แต่ด้วยการขยาย Walker คุณจะปรับแต่งโครงสร้างได้ด้วยการปรับเปลี่ยนเนื้อหา HTML

ไฟล์หลักที่เกี่ยวข้องกับคลาส Walker คือ wp-includes/class-wp-walker.php และควบคุมข้อมูลประเภทต้นไม้ที่เราระบุไว้ก่อนหน้านี้

เนื่องจากเป็นคลาส PHP ที่เป็นนามธรรม ในการสร้าง HTML ใดๆ นักพัฒนาจึงต้องขยายขอบเขตซึ่งจะกำหนดคุณสมบัติและวิธีการในเวอร์ชันที่กำหนดเอง เรามาศึกษาคลาสย่อยในไฟล์ class-wp-walker.php กัน

ชั้นเรียนเด็ก

$tree_type เป็นตัวแปรทางเลือกที่มาในประเภทหรืออาร์เรย์ของประเภทและกำหนดสิ่งที่คลาสจัดการ

 public $tree_type = array( 'post_type', 'taxonomy', 'custom' );

$db_fields เป็นตัวแปรที่จำเป็นและกำหนดฟิลด์ฐานข้อมูลที่จะใช้ คุณสมบัตินี้เป็นอาร์เรย์ที่มีสองคีย์: 'พาเรนต์' และ 'id' ที่มีค่าเป็นชื่อของคุณสมบัติของอ็อบเจ็กต์ที่มี id parent และ item id ตามลำดับ

 public $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id', );

คุณสมบัติ $max_pages ก็เป็นทางเลือกเช่นกัน และบทบาทของคุณสมบัติคือระบุจำนวนหน้าที่สูงสุดที่เพจวอล์คเกอร์ใช้

 public $max_pages = 1;

$has_children อธิบายตัวเองได้จริง ๆ และมีค่าจริงหรือเท็จขึ้นอยู่กับว่าองค์ประกอบปัจจุบันมีลูกหรือไม่

 public $has_children;

เมธอด start_lvl ถูกดำเนินการบนรูทของอ็อบเจ็กต์ที่มีลักษณะเหมือนต้นไม้ใหม่ และรับอาร์กิวเมนต์ $output, $depth และ $args

 public function start_lvl( &$output, $depth = 0, $args = array() ) {}

อาร์กิวเมนต์ $output ท้ายเนื้อหาเพิ่มเติม ส่วนค่า $depth ระบุความลึกของรายการ และ $args เป็นอาร์เรย์ของอาร์กิวเมนต์เพิ่มเติม

เมธอด end_lvl จะปิดแท็กใดๆ ก็ตามที่เคยเปิดโดยเมธอด start_lvl

 public function end_lvl( &$output, $depth = 0, $args = array() ) {}

start_el (Start Element) ใช้เพื่อแสดงแท็ก HTML เปิดสำหรับองค์ประกอบปัจจุบัน ในกรณีของเมนู มักจะเป็นแท็ก <li>

 public function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {}

ฟังก์ชัน end_el ถูกเรียกหลังจากที่ Walker ส่งผ่านองค์ประกอบที่มีลูกทั้งหมดและส่งคืนแท็กปิด

 public function end_el( &$output, $object, $depth = 0, $args = array() ) {}

display_element แสดงองค์ประกอบของวัตถุต้นไม้จริง ๆ มันเรียก start_el , start_lvl , display_element , end_lvl , end_el ตามลำดับนี้ ทีนี้มาดูข้อโต้แย้งของมันกัน

  • $element : องค์ประกอบปัจจุบัน
  • $children_elements : องค์ประกอบย่อยทั้งหมดของวัตถุต้นไม้
  • $max_deep : ขีดจำกัดความลึกสูงสุดที่เราสามารถสำรวจได้
  • $ความลึก : ระดับที่เราอยู่ในขณะนี้ที่
  • $args : อาร์กิวเมนต์ทางเลือกเพิ่มเติม
  • $output : เอาต์พุต HTML ปัจจุบัน

ตอนนี้เราจะสาธิตตัวอย่างหนึ่งตัวอย่างสำหรับข้อมูลแต่ละประเภทโดยใช้การติดตั้ง WordPress โดยเปิดใช้งานธีม Twenty Twenty

การปรับแต่งโครงสร้างเมนู

ฟังก์ชัน wp_nav_menu() ที่ WordPress ใช้สำหรับแสดงเมนูจะรวมอยู่ใน wp-includes/nav-menu-template.php ในไฟล์นี้ WordPress ยังเรียกร้องให้คลาส Walker_Nav_Menu รอบบรรทัด 605

 function walk_nav_menu_tree( $items, $depth, $r ) { $walker = ( empty( $r->walker ) ) ? new Walker_Nav_Menu : $r->walker; return $walker->walk( $items, $depth, $r ); }

คลาส Walker_Nav_Menu ถูกกำหนดไว้ใน wp-includes/class-walker-nav-menu.php และโดยพื้นฐานแล้วมันคือเนื้อหาทั้งหมดของไฟล์

ในการแสดงผลลัพธ์ของเมนู โค้ด WordPress จะใช้คุณสมบัติและวิธีการของคลาส Walker_Nav_Menu ที่อธิบายไว้ในไฟล์นี้

ตัวอย่างเช่น แก้ไขปัญหาที่รู้จักกันดีที่นักพัฒนาหลายคนเผชิญ ซึ่งก็คือการเปลี่ยนองค์ประกอบสำหรับรายการเมนูหลักด้วยลิงก์แบบกำหนดเองที่ว่างเปล่า ('#') เพื่อป้องกันไม่ให้ผู้เยี่ยมชมคลิกลิงก์เหล่านั้น

เพื่อให้เราสามารถเปรียบเทียบผลลัพธ์ของเรา ขั้นแรกให้สร้างโคลนของเมนูหลักโดยเพียงแค่เพิ่มโค้ดด้านล่างใน header.php ทันทีหลังจากเริ่มต้นองค์ประกอบ <header>

 <header class="header-footer-group" role="banner"> <?php wp_nav_menu( array( 'menu_class' => 'primary-menu reset-list-style' ) ); ?>

สิ่งที่เราทำจริง ๆ ที่นี่คือการสร้างเมนูหลักขึ้นมาใหม่และสืบทอดฟังก์ชันการทำงานแบบหล่นลงและ CSS โดยการเพิ่มคลาส primary-menu reset-list-style ให้กับเมนูใหม่เช่นกัน

ในไฟล์ functions.php ของเรา เราจะสร้างคลาสที่ขยายคลาส Walker_Nav_Menu เนื่องจากเราต้องการเปลี่ยนประเภทขององค์ประกอบ เราจะแทนที่เมธอด start_el

 if ( !class_exists('My_Custom_Nav_Walker') ) { class My_Custom_Nav_Walker extends Walker_Nav_Menu { function start_el(&$output, $item, $depth=0, $args=[], $id=0) { $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>'; } } } }

ดังนั้นเราจึงห่อแต่ละองค์ประกอบตามปกติด้วยแท็ก <li> จากนั้นใช้คำสั่ง if ต่อท้ายช่วงเมื่อลิงก์คือ “#” และแท็ก <a> สำหรับส่วนที่เหลือ

เพื่อใช้สิ่งนี้กับเมนูของเรา เรากลับไปที่รหัสเมนูที่เราเพิ่มไว้ก่อนหน้านี้และระบุพารามิเตอร์วอล์คเกอร์:

 wp_nav_menu( array( 'walker' => new My_Custom_Nav_Walker, 'menu_class' => 'primary-menu reset-list-style' ) );

ตอนนี้ผลลัพธ์ควรมีลักษณะดังนี้:

หากคุณวางเมาส์เหนือ 'บริการ' ในรายการเมนู จะไม่มีเคอร์เซอร์มือปรากฏขึ้น และรายการเมนูนี้จะไม่สามารถคลิกได้ เมนูย่อยแบบเลื่อนลงจะยังคงแสดงอย่างถูกต้องอย่างไรก็ตาม

การปรับแต่ง หมวดหมู่

ขั้นแรกให้ไปที่ส่วนผู้ดูแลระบบแล้วสร้างหมวดหมู่โพสต์และหมวดหมู่ย่อยเพื่อให้มีแผนผังหมวดหมู่สำหรับการสาธิต

หลังจากนั้นเราจะสร้างรายการหมวดหมู่โดยเพิ่มรหัสนี้ที่ใดที่หนึ่งใน header.php คุณสามารถวางไว้หลังจุดเริ่มต้นขององค์ประกอบส่วนหัวเหมือนก่อนหน้านี้

 <header class="header-footer-group" role="banner"> <?php wp_list_categories( array('hide_empty' => FALSE) ); ?>

ฟังก์ชันนี้เป็นฟังก์ชัน WordPress ในตัวที่สร้างเอาต์พุต HTML ของแผนผังหมวดหมู่ โดยค่าเริ่มต้น จะแสดงเฉพาะหมวดหมู่ที่มีโพสต์ นั่นคือเหตุผลที่เราใช้ตัวเลือก hide_empty เพื่อแสดงหมวดหมู่ว่างเช่นกัน และดูลำดับชั้นทั้งหมดสำหรับจุดประสงค์ของตัวอย่างนี้

ก่อนหน้านี้ เราสามารถสร้างคลาสแบบกำหนดเองใน functions.php เพื่อขยาย Walker_Category Class เริ่มต้นที่อธิบายไว้ใน wp-includes/class-walker-category.php และใช้การเปลี่ยนแปลงของเรา ตัวอย่างเช่น เราจะเพิ่มไอคอนก่อนชื่อหมวดหมู่โดยเพิ่มรหัสนี้:

 if ( !class_exists('My_Category_tree_Walker') ) { class My_Category_tree_Walker extends Walker_Category { function start_el(&$output, $item, $depth=0, $args=array(),$current_object_id = 0) { $output.= '<li><a href="'.home_url('category/'.$item->slug).'"> <img src="http://path/to/mages/'.($item->slug).'.jpg"> '.esc_attr($item->name); } } }

เพื่อให้ใช้งานได้ คุณจะต้องเตรียมรูปภาพที่เหมาะสมและบันทึกไว้ในโฟลเดอร์ที่กำหนด รูปภาพเหล่านี้จะต้องอยู่ในรูปแบบชื่อเฉพาะ ซึ่งในตัวอย่างนี้จะเป็น “post-category-1”, “post-subcategory-1”, “post-category-3.jpg” เป็นต้น

ปรับแต่งความคิดเห็น

การอัปเดตรายการเมนูและหมวดหมู่เป็นสาเหตุที่พบบ่อยที่สุดว่าทำไมคุณอาจปรับแต่ง Walker Class แต่บางครั้งคุณต้องใช้เทคนิคเดียวกันนี้สำหรับความคิดเห็นด้วย ตัวอย่างเช่น หากคุณต้องการเปลี่ยนข้อมูลเมตาข้างรูปภาพ Gravatar ในส่วนความคิดเห็น เราสามารถทำได้โดยง่ายโดยขยายคลาส Walker_Comment ที่พบในไฟล์ wp-includes/class-walker-comment.php

ในไฟล์ functions.php เพิ่มรหัสนี้

 if ( !class_exists('My_Comment_Walker') ) { class My_Comment_Walker extends Walker_Comment { protected function html5_comment( $comment, $depth, $args ) { $tag = ( 'div' === $args['style'] ) ? 'div' : 'li'; ?> <<?php echo $tag; ?> <?php comment_class( $this->has_children ? 'parent' : '', $comment ); ?>> <article class="comment-body"> <footer class="comment-meta"> <div class="comment-author vcard"> <?php if ( 0 != $args['avatar_size'] ) echo get_avatar( $comment, $args['avatar_size'] ); ?> <?php printf( __( '%s <span class="says">says:</span>' ), sprintf( '<span class="fn">%s</span>', get_comment_author_link( $comment ) ) ); ?> </div><!-- .comment-author --> <div class="comment-metadata"> <?php $user_id=$comment->user_id; ?> <p class="commenter-bio"><?php the_author_meta('description',$user_id); ?></p> <p class="commenter-url"><a href="<?php the_author_meta('user_url',$user_id); ?>" target="_blank"><?php the_author_meta('user_url',$user_id); ?></a></p> </div><!-- .comment-metadata --> <?php if ( '0' == $comment->comment_approved ) : ?> <p class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.' ); ?></p> <?php endif; ?> </footer><!-- .comment-meta --> <div class="comment-content"> <?php comment_text(); ?> </div><!-- .comment-content --> <?php comment_reply_link( array_merge( $args, array( 'add_below' => 'div-comment', 'depth' => $depth, 'max_depth' => $args['max_depth'], 'before' => '<div class="reply">', 'after' => '</div>' ) ) ); ?> </article><!-- .comment-body --> <?php } } }

ดังที่คุณสังเกตเห็นได้โดยการเปรียบเทียบโค้ด about กับเนื้อหาของ Walker_Comment ต้นฉบับ การเปลี่ยนแปลงเพียงอย่างเดียวที่จำเป็นคือในวิธี html5_comment ซึ่งโดยทั่วไปจะแสดงความคิดเห็นในรูปแบบ HTML5

หลังจากนั้นเราต้องแสดงรายการความคิดเห็นโดยใช้ฟังก์ชัน wp_list_comments ในตัวพร้อมอาร์กิวเมนต์ที่ถูกต้องเพื่อแสดง HTML วัตถุเหมือนต้นไม้ความคิดเห็น

 wp_list_comments( array( 'page' => 143, 'walker' => new My_Comment_Walker ));

เราแทรกโค้ดในบรรทัดเดียวกันกับ header.php ที่เราทำก่อนหน้านี้ และใช้ ID ของโพสต์ที่มีความคิดเห็น แน่นอน คุณสามารถแทนที่โค้ดที่เกี่ยวข้องกับความคิดเห็นของเทมเพลตของคุณแทนและข้ามตัวเลือก 'หน้า' เพื่อให้ใช้กับส่วนความคิดเห็นของบทความทั้งหมดของคุณได้

หากคุณรีเฟรชส่วนหน้าของเว็บไซต์ของคุณตอนนี้ คุณจะสังเกตเห็นรายการข้อมูลเพิ่มเติม (ประวัติผู้เขียนและ URL ผู้เขียน) ที่เราเพิ่มในโค้ดที่กำหนดเองด้านบน

บทสรุป

หวังว่าข้อมูลข้างต้นจะทำให้คุณมีความเข้าใจอย่างลึกซึ้งเกี่ยวกับการใช้ WordPress Walker Class ในตัวอย่างทั้งหมด เราใช้การเปลี่ยนแปลงโดยตรงกับไฟล์ธีมหลัก แม้ว่าจะเป็นการดีสำหรับการสาธิต คุณจะต้องแน่ใจว่าคุณใช้การแก้ไขเฉพาะกับธีมย่อยเท่านั้นในทางปฏิบัติ เพื่อให้แน่ใจว่าการอัปเดตเหล่านี้จะไม่ถูกเขียนทับเมื่อมีการอัปเดต WordPress หรือธีมที่ใช้