熟悉 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_el
、 start_lvl
、 display_element
、 end_lvl
、 end_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 或使用的主题时这些更新不会被覆盖。