Walker は、WordPress コアがツリー状のデータ構造をレンダリングする際の動作を定義するための「抽象クラス」です。
WordPress コアではデータの種類ごとに Walker を継承したクラスが定義されており、デベロッパーも Walker を継承することで独自の動作を定義することができます。
Walker
のプロパティとメソッド
Walker
は抽象クラスです。
タップして Walker 抽象クラスのソースコードを確認…
以下、WorePress コアの中で定義されている Walker
クラスのソースコードを転載しています。ファイルは、wp-includes/
の中にあります。
- <?php
-
- /**
- * A class for displaying various tree-like structures.
- *
- * Extend the Walker class to use it, see examples below. Child classes
- * do not need to implement all of the abstract methods in the class. The child
- * only needs to implement the methods that are needed.
- *
- * @since 2.1.0
- *
- * @package WordPress
- * @abstract
- */
- class Walker
- {
- /**
- * What the class handles.
- *
- * @since 2.1.0
- * @var string
- */
- public $tree_type;
-
- /**
- * DB fields to use.
- *
- * @since 2.1.0
- * @var array
- */
- public $db_fields;
-
- /**
- * Max number of pages walked by the paged walker
- *
- * @since 2.7.0
- * @var int
- */
- public $max_pages = 1;
-
- /**
- * Whether the current element has children or not.
- *
- * To be used in start_el().
- *
- * @since 4.0.0
- * @var bool
- */
- public $has_children;
-
- /**
- * Starts the list before the elements are added.
- *
- * The $args parameter holds additional values that may be used with the child
- * class methods. This method is called at the start of the output list.
- *
- * @since 2.1.0
- * @abstract
- *
- * @param string $output Used to append additional content (passed by reference).
- * @param int $depth Depth of the item.
- * @param array $args An array of additional arguments.
- */
- public function start_lvl(&$output, $depth = 0, $args = [])
- {
- }
-
- /**
- * Ends the list of after the elements are added.
- *
- * The $args parameter holds additional values that may be used with the child
- * class methods. This method finishes the list at the end of output of the elements.
- *
- * @since 2.1.0
- * @abstract
- *
- * @param string $output Used to append additional content (passed by reference).
- * @param int $depth Depth of the item.
- * @param array $args An array of additional arguments.
- */
- public function end_lvl(&$output, $depth = 0, $args = [])
- {
- }
-
- /**
- * Start the element output.
- *
- * The $args parameter holds additional values that may be used with the child
- * class methods. Includes the element output also.
- *
- * @since 2.1.0
- * @abstract
- *
- * @param string $output Used to append additional content (passed by reference).
- * @param object $object The data object.
- * @param int $depth Depth of the item.
- * @param array $args An array of additional arguments.
- * @param int $current_object_id ID of the current item.
- */
- public function start_el(&$output, $object, $depth = 0, $args = [], $current_object_id = 0)
- {
- }
-
- /**
- * Ends the element output, if needed.
- *
- * The $args parameter holds additional values that may be used with the child class methods.
- *
- * @since 2.1.0
- * @abstract
- *
- * @param string $output Used to append additional content (passed by reference).
- * @param object $object The data object.
- * @param int $depth Depth of the item.
- * @param array $args An array of additional arguments.
- */
- public function end_el(&$output, $object, $depth = 0, $args = [])
- {
- }
-
- /**
- * Traverse elements to create list from elements.
- *
- * Display one element if the element doesn't have any children otherwise,
- * display the element and its children. Will only traverse up to the max
- * depth and no ignore elements under that depth. It is possible to set the
- * max depth to include all depths, see walk() method.
- *
- * This method should not be called directly, use the walk() method instead.
- *
- * @since 2.5.0
- *
- * @param object $element Data object.
- * @param array $children_elements List of elements to continue traversing (passed by reference).
- * @param int $max_depth Max depth to traverse.
- * @param int $depth Depth of current element.
- * @param array $args An array of arguments.
- * @param string $output Used to append additional content (passed by reference).
- */
- public function display_element($element, &$children_elements, $max_depth, $depth, $args, &$output)
- {
- if (!$element) {
- return;
- }
-
- $id_field = $this->db_fields['id'];
- $id = $element->$id_field;
-
- //display this element
- $this->has_children = !empty($children_elements[$id]);
- if (isset($args[0]) && is_array($args[0])) {
- $args[0]['has_children'] = $this->has_children; // Back-compat.
- }
-
- $cb_args = array_merge([&$output, $element, $depth], $args);
- call_user_func_array([$this, 'start_el'], $cb_args);
-
- // descend only when the depth is right and there are childrens for this element
- if (($max_depth == 0 || $max_depth > $depth + 1) && isset($children_elements[$id])) {
-
- foreach ($children_elements[$id] as $child) {
-
- if (!isset($newlevel)) {
- $newlevel = true;
- //start the child delimiter
- $cb_args = array_merge([&$output, $depth], $args);
- call_user_func_array([$this, 'start_lvl'], $cb_args);
- }
- $this->display_element($child, $children_elements, $max_depth, $depth + 1, $args, $output);
- }
- unset($children_elements[$id]);
- }
-
- if (isset($newlevel) && $newlevel) {
- //end the child delimiter
- $cb_args = array_merge([&$output, $depth], $args);
- call_user_func_array([$this, 'end_lvl'], $cb_args);
- }
-
- //end this element
- $cb_args = array_merge([&$output, $element, $depth], $args);
- call_user_func_array([$this, 'end_el'], $cb_args);
- }
-
- /**
- * Display array of elements hierarchically.
- *
- * Does not assume any existing order of elements.
- *
- * $max_depth = -1 means flatly display every element.
- * $max_depth = 0 means display all levels.
- * $max_depth > 0 specifies the number of display levels.
- *
- * @since 2.1.0
- *
- * @param array $elements An array of elements.
- * @param int $max_depth The maximum hierarchical depth.
- *
- * @return string The hierarchical item output.
- */
- public function walk($elements, $max_depth)
- {
- $args = array_slice(func_get_args(), 2);
- $output = '';
-
- //invalid parameter or nothing to walk
- if ($max_depth < -1 || empty($elements)) {
- return $output;
- }
-
- $parent_field = $this->db_fields['parent'];
-
- // flat display
- if (-1 == $max_depth) {
- $empty_array = [];
- foreach ($elements as $e) {
- $this->display_element($e, $empty_array, 1, 0, $args, $output);
- }
-
- return $output;
- }
-
- /*
- * Need to display in hierarchical order.
- * Separate elements into two buckets: top level and children elements.
- * Children_elements is two dimensional array, eg.
- * Children_elements[10][] contains all sub-elements whose parent is 10.
- */
- $top_level_elements = [];
- $children_elements = [];
- foreach ($elements as $e) {
- if (empty($e->$parent_field)) {
- $top_level_elements[] = $e;
- } else {
- $children_elements[$e->$parent_field][] = $e;
- }
- }
-
- /*
- * When none of the elements is top level.
- * Assume the first one must be root of the sub elements.
- */
- if (empty($top_level_elements)) {
-
- $first = array_slice($elements, 0, 1);
- $root = $first[0];
-
- $top_level_elements = [];
- $children_elements = [];
- foreach ($elements as $e) {
- if ($root->$parent_field == $e->$parent_field) {
- $top_level_elements[] = $e;
- } else {
- $children_elements[$e->$parent_field][] = $e;
- }
- }
- }
-
- foreach ($top_level_elements as $e) {
- $this->display_element($e, $children_elements, $max_depth, 0, $args, $output);
- }
-
- /*
- * If we are displaying all levels, and remaining children_elements is not empty,
- * then we got orphans, which should be displayed regardless.
- */
- if (($max_depth == 0) && count($children_elements) > 0) {
- $empty_array = [];
- foreach ($children_elements as $orphans) {
- foreach ($orphans as $op) {
- $this->display_element($op, $empty_array, 1, 0, $args, $output);
- }
- }
- }
-
- return $output;
- }
-
- /**
- * paged_walk() - produce a page of nested elements
- *
- * Given an array of hierarchical elements, the maximum depth, a specific page number,
- * and number of elements per page, this function first determines all top level root elements
- * belonging to that page, then lists them and all of their children in hierarchical order.
- *
- * $max_depth = 0 means display all levels.
- * $max_depth > 0 specifies the number of display levels.
- *
- * @since 2.7.0
- *
- * @param array $elements
- * @param int $max_depth The maximum hierarchical depth.
- * @param int $page_num The specific page number, beginning with 1.
- * @param int $per_page
- *
- * @return string XHTML of the specified page of elements
- */
- public function paged_walk($elements, $max_depth, $page_num, $per_page)
- {
- if (empty($elements) || $max_depth < -1) {
- return '';
- }
-
- $args = array_slice(func_get_args(), 4);
- $output = '';
-
- $parent_field = $this->db_fields['parent'];
-
- $count = -1;
- if (-1 == $max_depth) {
- $total_top = count($elements);
- }
- if ($page_num < 1 || $per_page < 0) {
- // No paging
- $paging = false;
- $start = 0;
- if (-1 == $max_depth) {
- $end = $total_top;
- }
- $this->max_pages = 1;
- } else {
- $paging = true;
- $start = ((int)$page_num - 1) * (int)$per_page;
- $end = $start + $per_page;
- if (-1 == $max_depth) {
- $this->max_pages = ceil($total_top / $per_page);
- }
- }
-
- // flat display
- if (-1 == $max_depth) {
- if (!empty($args[0]['reverse_top_level'])) {
- $elements = array_reverse($elements);
- $oldstart = $start;
- $start = $total_top - $end;
- $end = $total_top - $oldstart;
- }
-
- $empty_array = [];
- foreach ($elements as $e) {
- $count++;
- if ($count < $start) {
- continue;
- }
- if ($count >= $end) {
- break;
- }
- $this->display_element($e, $empty_array, 1, 0, $args, $output);
- }
-
- return $output;
- }
-
- /*
- * Separate elements into two buckets: top level and children elements.
- * Children_elements is two dimensional array, e.g.
- * $children_elements[10][] contains all sub-elements whose parent is 10.
- */
- $top_level_elements = [];
- $children_elements = [];
- foreach ($elements as $e) {
- if (0 == $e->$parent_field) {
- $top_level_elements[] = $e;
- } else {
- $children_elements[$e->$parent_field][] = $e;
- }
- }
-
- $total_top = count($top_level_elements);
- if ($paging) {
- $this->max_pages = ceil($total_top / $per_page);
- } else {
- $end = $total_top;
- }
-
- if (!empty($args[0]['reverse_top_level'])) {
- $top_level_elements = array_reverse($top_level_elements);
- $oldstart = $start;
- $start = $total_top - $end;
- $end = $total_top - $oldstart;
- }
- if (!empty($args[0]['reverse_children'])) {
- foreach ($children_elements as $parent => $children) {
- $children_elements[$parent] = array_reverse($children);
- }
- }
-
- foreach ($top_level_elements as $e) {
- $count++;
-
- // For the last page, need to unset earlier children in order to keep track of orphans.
- if ($end >= $total_top && $count < $start) {
- $this->unset_children($e, $children_elements);
- }
-
- if ($count < $start) {
- continue;
- }
-
- if ($count >= $end) {
- break;
- }
-
- $this->display_element($e, $children_elements, $max_depth, 0, $args, $output);
- }
-
- if ($end >= $total_top && count($children_elements) > 0) {
- $empty_array = [];
- foreach ($children_elements as $orphans) {
- foreach ($orphans as $op) {
- $this->display_element($op, $empty_array, 1, 0, $args, $output);
- }
- }
- }
-
- return $output;
- }
-
- /**
- * Calculates the total number of root elements.
- *
- * @since 2.7.0
- *
- * @param array $elements Elements to list.
- *
- * @return int Number of root elements.
- */
- public function get_number_of_root_elements($elements)
- {
- $num = 0;
- $parent_field = $this->db_fields['parent'];
-
- foreach ($elements as $e) {
- if (0 == $e->$parent_field) {
- $num++;
- }
- }
-
- return $num;
- }
-
- /**
- * Unset all the children for a given top level element.
- *
- * @since 2.7.0
- *
- * @param object $e
- * @param array $children_elements
- */
- public function unset_children($e, &$children_elements)
- {
- if (!$e || !$children_elements) {
- return;
- }
-
- $id_field = $this->db_fields['id'];
- $id = $e->$id_field;
-
- if (!empty($children_elements[$id]) && is_array($children_elements[$id])) {
- foreach ((array)$children_elements[$id] as $child) {
- $this->unset_children($child, $children_elements);
- }
- }
-
- unset($children_elements[$id]);
- }
-
- } // Walker
Walker
には以下のプロパティやメソッドが含まれています。
プロパティ
$tree_type
- クラスが処理するもの。例えば、
category
やcomment
など。 $db_fields
- 親 ID、項目 IDの指定。
$max_pages
paged_walk()
メソッドに使用される。$has_children
display_element()
メソッドに使用される。
カスタマイズの際、これら項目を意識することはほとんどないでしょう。意味が理解できなくても問題ありません。
抽象メソッド
4つの抽象メソッドをどのように実装するかで動作が決まります(なので重要です!)。それぞれのメソッドは、Walker がツリーを移動する際に、レベルまたは要素に応じて開始また終了のタイミングでレンダリングを行います。
レベルはすなわちブランチです。HTMLでいうところの <ul>
や <ol>
になりますが、レンダリングはこれらの要素でなくてもOKです。
一方、要素はツリーの項目です。HTMLでいうところの <li>
になります。レベル同様こちらも <li>
以外を使うことができます。
function start_lvl(&$output, $depth = 0, $args = [])
- 開始レベル。一般的には、
<ul>
や<ol>
、<div>
。 function end_lvl(&$output, $depth = 0, $args = [])
- 終了レベル。一般的には、
</ul>
や</ol>
、</div>
。 function start_el(&$output, $object, $depth = 0, $args = [], $current_object_id = 0)
- 開始要素。一般的には、
<li>
や<span>
、<a>
。 function end_el(&$output, $object, $depth = 0, $args = [])
- 終了要素。一般的には、
</li>
や</span>
、</a>
。
パブリックメソッド
自らパブリックメソッドを使用することも可能ですが、基本的に使用しないでしょう。プロパティと同様に重要ではありません。
function walk($elements, $max_depth)
- ツリー構造を表示します。
function paged_walk( $elements, $max_depth, $page_num, $per_page )
- ツリー構造を表示します。これは、ページ機能を含みます。
function get_number_of_root_elements( $elements )
- ルート要素の総数を計算します。
function unset_children( $e, &$children_elements )
- 指定されたトップレベル要素のすべての子を削除します。
コアで定義されている Walker 派生のクラス
WordPressコアでは既にいくつかの Walker から派生したクラスが定義されており、WordPress 関数で利用されています。
class Walker_Category
- テンプレートタグ wp_list_categories() での走査を定義しており、独自の Walker を指定することもできます。
class Walker_CategoryDropdown
- テンプレートタグ wp_dropdown_categories() での走査を定義しています。
class Walker_Comment
- テンプレートタグ wp_list_comments() での走査を定義しており、独自の Walker を指定することもできます。
class Walker_Nav_Menu
- テンプレートタグ wp_nav_menu() での走査を定義しており、独自の Walker を指定することもできます。
class Walker_Page
- テンプレートタグ wp_list_pages() での走査を定義しており、独自の Walker を指定することもできます。
class Walker_PageDropdown
- テンプレートタグ wp_dropdown_pages() での走査を定義しています。
独自の Walker を作成して使う手順
前述のとおり、いくつかのテンプレートタグはコアが定義している Walker
を内部で使用しており、引数で独自の Walker
を指定して動作を変更できるようになっています。ここでは、ナビゲーションメニューを表示するテンプレートタグ wp_nav_menu()
を、独自の Walker を作成して動作を変更する流れを紹介します。
テンプレートタグ/wp nav menu
WordPress Codex 日本語版のドキュメントページに詳細が載っていますが、wp_nav_menu()
は引数に配列で様々なパラメーターを指定することでカスタマイズできます。そのうち、'walker'
パラメーターに Walker
オブジェクトを指定するとツリー走査の動作を変更することができます。
- <?php
- wp_nav_menu([
- 'menu' => '',
- 'menu_class' => 'menu',
- 'menu_id' => '{メニューのスラッグ}-{連番}',
- 'container' => 'div',
- 'container_class' => 'menu-{メニューのスラッグ}-container',
- 'container_id' => '',
- 'fallback_cb' => 'wp_page_menu',
- 'before' => '',
- 'after' => '',
- 'link_before' => '',
- 'link_after' => '',
- 'echo' => true,
- 'depth' => 0,
- 'walker' => new Walker_Nav_Menu(),
- 'theme_location' => '',
- 'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
- ]);
カスタムウォーカーは Walker
クラスを継承して作成してもいいのですが、Walker_Nav_Menu
を継承してオーバーライドしていった方が賢明です。なぜなら、4つのメソッドを記述するだけで済むからです。
このように…
- <?php
-
- class MyWalkerNavMenu extends Walker_Nav_Menu
- {
- public function start_lvl(&$output, $depth = 0, $args = [])
- {
- $output .= '<ul class="nav-list">';
- }
-
- public function end_lvl(&$output, $depth = 0, $args = [])
- {
- $output .= '</ul>';
- }
-
- function start_el(&$output, $item, $depth = 0, $args = [], $id = 0)
- {
- $output .= '<li class="nav-item">';
- $output .= sprintf(
- '%1$s<a%2$s>%3$s%4$s%5$s</a>%6$s',
- $args->before,
- ' href="' . esc_url(($item->url)) . '"',
- $args->link_before,
- $item->title,
- $args->link_after,
- $args->after
- );
- }
-
- public function end_el(&$output, $item, $depth = 0, $args = [])
- {
- $output .= '</li>';
- }
- }
これは実用性がない単純な例ですが、記述の仕方が理解し易くなっていると思います。
ここで、実際のWalker_Nav_Menu
のソースコードが気になる場合は下記を参照してください。もっと複雑な作りになっていますが、基本は上記のものと同じです。
タップして Walker_Nav_Menu クラスのソースコードを確認…
- <?php
- /**
- * Nav Menu API: Walker_Nav_Menu class
- *
- * @package WordPress
- * @subpackage Nav_Menus
- * @since 4.6.0
- */
-
- /**
- * Core class used to implement an HTML list of nav menu items.
- *
- * @since 3.0.0
- *
- * @see Walker
- */
- class Walker_Nav_Menu extends Walker {
- /**
- * What the class handles.
- *
- * @since 3.0.0
- * @var string
- *
- * @see Walker::$tree_type
- */
- public $tree_type = array( 'post_type', 'taxonomy', 'custom' );
-
- /**
- * Database fields to use.
- *
- * @since 3.0.0
- * @todo Decouple this.
- * @var array
- *
- * @see Walker::$db_fields
- */
- public $db_fields = array(
- 'parent' => 'menu_item_parent',
- 'id' => 'db_id',
- );
-
- /**
- * Starts the list before the elements are added.
- *
- * @since 3.0.0
- *
- * @see Walker::start_lvl()
- *
- * @param string $output Used to append additional content (passed by reference).
- * @param int $depth Depth of menu item. Used for padding.
- * @param stdClass $args An object of wp_nav_menu() arguments.
- */
- public function start_lvl( &$output, $depth = 0, $args = null ) {
- if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
- $t = '';
- $n = '';
- } else {
- $t = "\t";
- $n = "\n";
- }
- $indent = str_repeat( $t, $depth );
-
- // Default class.
- $classes = array( 'sub-menu' );
-
- /**
- * Filters the CSS class(es) applied to a menu list element.
- *
- * @since 4.8.0
- *
- * @param string[] $classes Array of the CSS classes that are applied to the menu `<ul>` element.
- * @param stdClass $args An object of `wp_nav_menu()` arguments.
- * @param int $depth Depth of menu item. Used for padding.
- */
- $class_names = join( ' ', apply_filters( 'nav_menu_submenu_css_class', $classes, $args, $depth ) );
- $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
-
- $output .= "{$n}{$indent}<ul$class_names>{$n}";
- }
-
- /**
- * Ends the list of after the elements are added.
- *
- * @since 3.0.0
- *
- * @see Walker::end_lvl()
- *
- * @param string $output Used to append additional content (passed by reference).
- * @param int $depth Depth of menu item. Used for padding.
- * @param stdClass $args An object of wp_nav_menu() arguments.
- */
- public function end_lvl( &$output, $depth = 0, $args = null ) {
- if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
- $t = '';
- $n = '';
- } else {
- $t = "\t";
- $n = "\n";
- }
- $indent = str_repeat( $t, $depth );
- $output .= "$indent</ul>{$n}";
- }
-
- /**
- * Starts the element output.
- *
- * @since 3.0.0
- * @since 4.4.0 The {@see 'nav_menu_item_args'} filter was added.
- *
- * @see Walker::start_el()
- *
- * @param string $output Used to append additional content (passed by reference).
- * @param WP_Post $item Menu item data object.
- * @param int $depth Depth of menu item. Used for padding.
- * @param stdClass $args An object of wp_nav_menu() arguments.
- * @param int $id Current item ID.
- */
- public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) {
- if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
- $t = '';
- $n = '';
- } else {
- $t = "\t";
- $n = "\n";
- }
- $indent = ( $depth ) ? str_repeat( $t, $depth ) : '';
-
- $classes = empty( $item->classes ) ? array() : (array) $item->classes;
- $classes[] = 'menu-item-' . $item->ID;
-
- /**
- * Filters the arguments for a single nav menu item.
- *
- * @since 4.4.0
- *
- * @param stdClass $args An object of wp_nav_menu() arguments.
- * @param WP_Post $item Menu item data object.
- * @param int $depth Depth of menu item. Used for padding.
- */
- $args = apply_filters( 'nav_menu_item_args', $args, $item, $depth );
-
- /**
- * Filters the CSS classes applied to a menu item's list item element.
- *
- * @since 3.0.0
- * @since 4.1.0 The `$depth` parameter was added.
- *
- * @param string[] $classes Array of the CSS classes that are applied to the menu item's `<li>` element.
- * @param WP_Post $item The current menu item.
- * @param stdClass $args An object of wp_nav_menu() arguments.
- * @param int $depth Depth of menu item. Used for padding.
- */
- $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth ) );
- $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
-
- /**
- * Filters the ID applied to a menu item's list item element.
- *
- * @since 3.0.1
- * @since 4.1.0 The `$depth` parameter was added.
- *
- * @param string $menu_id The ID that is applied to the menu item's `<li>` element.
- * @param WP_Post $item The current menu item.
- * @param stdClass $args An object of wp_nav_menu() arguments.
- * @param int $depth Depth of menu item. Used for padding.
- */
- $id = apply_filters( 'nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args, $depth );
- $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
-
- $output .= $indent . '<li' . $id . $class_names . '>';
-
- $atts = array();
- $atts['title'] = ! empty( $item->attr_title ) ? $item->attr_title : '';
- $atts['target'] = ! empty( $item->target ) ? $item->target : '';
- if ( '_blank' === $item->target && empty( $item->xfn ) ) {
- $atts['rel'] = 'noopener noreferrer';
- } else {
- $atts['rel'] = $item->xfn;
- }
- $atts['href'] = ! empty( $item->url ) ? $item->url : '';
- $atts['aria-current'] = $item->current ? 'page' : '';
-
- /**
- * Filters the HTML attributes applied to a menu item's anchor element.
- *
- * @since 3.6.0
- * @since 4.1.0 The `$depth` parameter was added.
- *
- * @param array $atts {
- * The HTML attributes applied to the menu item's `<a>` element, empty strings are ignored.
- *
- * @type string $title Title attribute.
- * @type string $target Target attribute.
- * @type string $rel The rel attribute.
- * @type string $href The href attribute.
- * @type string $aria_current The aria-current attribute.
- * }
- * @param WP_Post $item The current menu item.
- * @param stdClass $args An object of wp_nav_menu() arguments.
- * @param int $depth Depth of menu item. Used for padding.
- */
- $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );
-
- $attributes = '';
- foreach ( $atts as $attr => $value ) {
- if ( is_scalar( $value ) && '' !== $value && false !== $value ) {
- $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
- $attributes .= ' ' . $attr . '="' . $value . '"';
- }
- }
-
- /** This filter is documented in wp-includes/post-template.php */
- $title = apply_filters( 'the_title', $item->title, $item->ID );
-
- /**
- * Filters a menu item's title.
- *
- * @since 4.4.0
- *
- * @param string $title The menu item's title.
- * @param WP_Post $item The current menu item.
- * @param stdClass $args An object of wp_nav_menu() arguments.
- * @param int $depth Depth of menu item. Used for padding.
- */
- $title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
-
- $item_output = $args->before;
- $item_output .= '<a' . $attributes . '>';
- $item_output .= $args->link_before . $title . $args->link_after;
- $item_output .= '</a>';
- $item_output .= $args->after;
-
- /**
- * Filters a menu item's starting output.
- *
- * The menu item's starting output only includes `$args->before`, the opening `<a>`,
- * the menu item's title, the closing `</a>`, and `$args->after`. Currently, there is
- * no filter for modifying the opening and closing `<li>` for a menu item.
- *
- * @since 3.0.0
- *
- * @param string $item_output The menu item's starting HTML output.
- * @param WP_Post $item Menu item data object.
- * @param int $depth Depth of menu item. Used for padding.
- * @param stdClass $args An object of wp_nav_menu() arguments.
- */
- $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
- }
-
- /**
- * Ends the element output, if needed.
- *
- * @since 3.0.0
- *
- * @see Walker::end_el()
- *
- * @param string $output Used to append additional content (passed by reference).
- * @param WP_Post $item Page data object. Not used.
- * @param int $depth Depth of page. Not Used.
- * @param stdClass $args An object of wp_nav_menu() arguments.
- */
- public function end_el( &$output, $item, $depth = 0, $args = null ) {
- if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
- $t = '';
- $n = '';
- } else {
- $t = "\t";
- $n = "\n";
- }
- $output .= "</li>{$n}";
- }
-
- } // Walker_Nav_Menu
自作のウォーカーを作成したらパラメーターに指定して使用します。
- <?php
- wp_nav_menu([
- 'walker' => new MyWalkerNavMenu(),
- ]);
まとめ
Walker
は、WordPress がツリー状のデータ構造を操作する際に使用する抽象クラスです。WordPress コアは、Walker を拡張したクラスをいくつか定義しており、特定のテンプレートタグでそれを使用しています。デベロッパーは、独自の Walker(カスタムウォーカー)を作成することで、それらテンプレートタグの動作を変更することができます。カスタムウォーカーは基本的に4つのメソッドをオーバーライドするだけで作成することができます。