熟悉 WordPress Walker 课程

已发表: 2020-11-27

如果您不熟悉 Walker 课程,请准备好对它对您的工作的帮助感到惊讶。 WordPress Walker 类在 WordPress 2.1 中实现,为开发人员提供一种遍历树状数据结构以呈现 HTML 的方法。 在本文中,我们将研究 walker 参数的工作原理以及如何自定义菜单、类别和评论中的输出。

我们走吧!

沃克类概述

在 WordPress 中,我们经常看到具有层次结构的对象,例如导航菜单、类别列表或评论列表

您可能已经知道,在树数据结构的情况下,一些元素是父元素,而另一些元素是它们的子元素。 “发布子类别 1”是“发布类别 1”的子项,对评论的回复是评论本身的子评论,“服务 1”是“服务”项的子菜单项。

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是必需的变量,它定义要使用的数据库字段。 该属性是一个具有两个键的数组:“parent”和“id”,其值是分别保存父 id 和项 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 (起始元素)方法用于显示当前元素的开始 HTML 标记。 例如,在菜单的情况下,它通常是一个 <li> 标签。

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

在 Walker 传递一个元素及其所有子元素并返回一个结束标记后,调用end_el函数。

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

display_element实际上显示了树对象的元素。 它按此顺序调用start_elstart_lvldisplay_elementend_lvlend_el函数。 现在让我们来看看它的论点。

  • $element : 当前元素
  • $children_elements : 树对象的所有子元素
  • $max_depth :我们可以探索的最大深度限制
  • $depth :我们目前所处的水平
  • $args : 额外的可选参数
  • $output :当前的 HTML 输出。

现在,我们将使用激活二十二十主题的 WordPress 安装来演示每种数据类型的一个示例。

自定义菜单结构

WordPress 用于显示菜单的 wp_nav_menu() 函数包含在wp-includes/nav-menu-template.php文件中。 在这个文件中,WordPress 还在第 605 行调用了 Walker_Nav_Menu 类。

 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>元素开始后的header.php中添加以下代码来创建主菜单的克隆。

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

我们实际上在这里所做的是重新生成主菜单并通过将其类primary-menu reset-list-style也添加到新菜单来继承其下拉功能和 CSS。

现在在我们的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 语句在链接为“#”时附加一个 span,其余部分使用 <a> 标记。

要将它应用到我们的菜单,我们回到我们之前添加的菜单代码并指定 walker 参数:

 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中创建一个自定义类来扩展wp-includes/class-walker-category.php文件中描述的默认 Walker_Category 类并应用我们的更改。 例如,我们将通过添加以下代码在类别名称前添加一些图标:

 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 类的最常见原因,但有时您也必须为评论实现相同的技术。 例如,如果您想更改评论部分中 Gravatar 图像旁边的元信息,我们可以通过扩展 wp-includes/class-walker-comment.php 文件中的 Walker_Comment 类轻松做到这一点。

在 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 类有所了解。 在所有示例中,我们将更改直接应用于核心主题文件。 虽然这对于演示目的来说很好,但您显然希望确保在实践中只对子主题应用编辑,以确保在更新 WordPress 或使用的主题时这些更新不会被覆盖。