首页 收藏 文章 闲言 友链

WordPress 主题开发:通过继承 Walker 类自定义菜单、评论列表 html 输出

2019-05-21 14:28:44 浏览:227 编辑:郑妙忠

前言:有时候需要自定义菜单和评论列表,通过 WordPress 的 Walker_Nav_Menu、Walker_Comment 类,就可以很方便的控制菜单、评论列表的输出 html 输出,其实就是各种参数的拼接。

自定义菜单输出(想了解评论列表输出的可以直接跳过)

涉及文件:function.php、header.php、comments.php

在 function.php 注册菜单;如果要控制菜单html输出,就要写一个继承 Walker_Nav_Menu 的类。继承 Walker 类看起来很多,其实复制粘贴后改几个单词就能用了。

<?php
  // 注册菜单
  register_nav_menus(array(
    'my-menu' => _('头部导航') // _() 多语言时用
  ));

  // 继承 Walker_Nav_Menu 的类
  class My_Menu_Walker extends Walker_Nav_Menu{
    function start_lvl(&$output, $depth = 0, $args = array()){
      if($depth == 0){// 判断当前菜单深度,0代表一级菜单
        $output .= '<ul>' // 一级菜单里面二级菜单的包裹开始标签
      }else if($depth == 1){
        $output .= '<div>' // 二级菜单里面三级菜单的包裹开始标签
      }
    }

    function end_lvl(&$output, $depth = 0, $args = array()){
      if($depth == 0){
        $output .= '</ul>' // 一级菜单里面二级菜单的包裹结束标签,要跟 start_lvl() 对应
      }else if($depth == 1){
        $output .= '</div>' // 二级菜单里面三级菜单的包裹结束标签,要跟 start_lvl() 对应
      }
    }

    // start_el() 是重点,菜单里面的 <a></a> 标签的html输出就是在这里控制
    function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0){
      if($depth == 0){
        $output .= '<li>' // 一级菜单里面元素的开始标签
      }else if($depth == 1){
        $output .= '<p>' // 二级菜单里面元素的开始标签
      }

      //判断当前元素里面是否包含有下级菜单
      if($args->walker->has_children){
        // 存在下级菜单
      }

      // <a>标签的内容
      $a_cont = apply_filters( 'the_title', $item->title, $item->ID );

      // <a>标签的参数
      $a_attr  = ' title="' . esc_attr($a_cont) . '"';
      $a_attr .= ' target="' . esc_attr($item->target) . '"'; // $item->target 获取后台设置的链接打开方式
      $a_attr .= ' rel="' . esc_attr($item->xfn) . '"';
      $a_attr .= ' href="' . esc_attr( $item->url) . '"'; // $item->url 获取后台设置的链接地址
      $a_attr .= ' class="' . join(' ', $item->classes) . '"'; // $item->classes 获取后台设置的类名,返回数据类型为 Array
      // 用 join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $item->classes ), $item, $args )); 过滤掉多余的自带类名。

      // 元素内容拼接
      $item_output = "$args->before<a$a_attr>$args->link_before$item->description$a_cont$args->link_after</a>$args->after";
      /*
      变量说明:
      $args->before:调用 wp_nav_menu() 时传入的 before 参数;$args->after 相同
      $a_attr:上面定义的变量
      $args->link_before:调用 wp_nav_menu() 时传入的 link_before 参数;$args->link_after 相同
      $item->description:获取后台设置的菜单图像描述,菜单图像描述默认不支持 html,如果要让图像描述支持 html,请移步到《WordPress 主题开发:修改默认设置》查看。
      $a_cont:上面定义的变量
      */

      $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }

    function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0){
      if($depth == 0){
        $output .= '</li>' // 一级菜单里面元素的结束标签
      }else if($depth == 1){
        $output .= '</p>' // 二级菜单里面元素的结束标签
      }
    }
  }
?>

让菜单图像描述支持 html 传送门:《WordPress 主题开发:修改默认设置》

已经写好 Walker 类,接着就要在调用wp_nav_menu()时使用它。菜单通过调用wp_nav_menu()输出,一般是写在 header.php 文件,也可以写在 footer.php 或 sidebar.php 文件中。

<?php
  // 放到自己要放的位置,就会自动输出。
  wp_nav_menu(array(
    'theme_location'  => 'my-menu', // 上面注册的菜单名
    'items_wrap'      => '<ul>%3$s</ul>',
    'walker'          => new My_Menu_Walker() // 上面继承 Walker_Nav_Menu 的类 My_Walker
  ));
?>

自定义评论列表输出(与菜单自定义差不多)

涉及文件:function.php、comments.php 文件

<?php
  // 写一个继承 Walker_Comment 的类
  class My_Comment_Walker extends Walker_Comment{
    function start_lvl( &$output, $depth = 0, $args = array() ){
      $output .= "<ul>";
    }
    function end_lvl( &$output, $depth = 0, $args = array() ){
      $output .= "</ul>";
    }

    // 这个函数是重点
    function start_el( &$output, $comment, $depth = 0, $args = array(), $id = 0 ){
      /* 首先是每一条评论的各种参数 */
      $id = $comment->comment_ID; // 获取评论id
      $name = $comment->comment_author; // 获取评论作者
      $url = $comment->comment_author_url; // 获取评论作者url
      $date = $comment->comment_date; // 获取评论日期
      $avatar = get_avatar($comment->comment_author_email, 64, '', $name, array('class' => 'comment-avatar')); // 通过评论邮箱地址,从 gravatar.com 获取头像

      // 评论内容处理,表情代码也在这里替换成<img>图片。
      $content = str_ireplace(array("\r\n","\n"),"<br>",$comment->comment_content); // 把换行符替换成 <br>

      /* 接着是输出 html 拼接 */
      $output .= "<li>";

      if( $depth == 0 ){
        // 如果是一级评论
        /* 这里可以根据需要,任意拼接每一条评论的参数 */
        $output .= "$avatar<a href=\"$url\">$name</a>:$content";
      }else{
       // 非一级评论,二级评论、三级评论等等
        $for = get_comment_author( $comment->comment_parent ); // 获取父评论作者名,@ 时用到

        /* 这里同样可以根据需要,任意拼接每一条评论的参数 */
        $output .= "<a href=\"$url\">$name</a>:@$for $content";// 添加 @ 符号
      }
      $output .= "<span onclock="customReply($id)">回复</span>";// customReply(comment_id) 是一个自定义的 js 函数,里面可以写自己想实现的功能,这里只是提供一个回复功能的思路。如果想 ajax 提交评论,请移步到《WordPress 主题开发:无刷新 ajax 提交评论》查看。
    }

    function end_el( &$output, $comment, $depth = 0, $args = array(), $id = 0 ){
      $output .= "</li>";
    }
  }
?>

接着在 comments.php 文件中通过wp_list_comments()接口函数使用它。

<?php
  // 放到自己要放的位置,就会自动输出。
  wp_list_comments(array(
    'walker' => new My_Comment_Walker() // 上面继承 Walker_Comment 的类 My_Walker
  ));
?>

ajax 提交评论传送门:《WordPress 主题开发:无刷新 ajax 提交评论》

END

留言 (共 0 条)