Typecho自定义二级菜单样式

楚天乐 8683 4 条

背景介绍

先来说说当前的菜单样式吧

  1. 系统默认菜单栏实现和样式
    // themes/default/sidebar.php 25行
    <?php if (!empty($this->options->sidebarBlock) && in_array('ShowCategory', $this->options->sidebarBlock)): ?>
    <section class="widget">
    <h3 class="widget-title"><?php _e('分类'); ?></h3>
    <?php $this->widget('Widget_Metas_Category_List')->listCategories('wrapClass=widget-list'); ?>
    </section>
    <?php endif; ?>

    默认模板调用了Widget_Metas_Category_List的listCategories方法来显示导航菜单,那么这个导航菜单的样式就被集成到了listCategories方法中。又是html+php混写。(大家吐槽的不是php, 而是写php的人)

显示效果呢,上个图吧
WeChat Screenshot_20180823111153.png

  1. 再来看看TypeD8是怎么实现的
    同上,先看代码

    <div class="navbar-wrap">
    <div class="navbar">
        <h1 class="logo"><a href="<?php $this->options->siteUrl(); ?>" title="<?php $this->options->title() ?>"><?php $this->options->title() ?></a></h1>
        <ul class="nav active" style="display">
            <li><a href="<?php $this->options->siteUrl(); ?>">Home</a></li>
    
                        <!---重点开始-->
            <?php $this->widget('Widget_Metas_Category_List')
           ->parse('<li class="menu-item"><a href="{permalink}">{name}</a></li>'); ?>
                        <!---重点结束-->
    
                        ..................其余省略,不重要............
    </div>
    </div>

TypeD8模板也是用了Widget_Metas_Category_List来输出分类,但是他没有使用listCategories方法输出内置的模板,而是用parse方法自定义了输出格式。这里,暂且先不去管这个parse的细节用法。
我们定义一个二级分类看看效果先。在Golang分类下定义一个子分类Network Programming with GO。显示效果如下图
WeChat Image_20180821122220.png

这就搞笑了,父分类和子分类显示在了同一个层级上。我本以为子分类会不显示的,毕竟我还too young too simple。

解决方案

有了前面那篇讲模板和数据分离的文章里的经验,这里就有了合适的解决方案。前面那篇文章链接如下:
http://blog.shyclouds.net/typecho/%E4%BC%98%E9%9B%85%E5%9C%B0%E8%87%AA%E5%AE%9A%E4%B9%89%E9%81%8D%E5%8E%86%E8%BE%93%E5%87%BA%E6%96%87%E7%AB%A0.html

$this->widget('Widget_Metas_Category_List')
           ->parse('<li class="menu-item"><a href="{permalink}">{name}</a></li>');

或者

$this->widget('Widget_Metas_Category_List')->listCategories('wrapClass=widget-list');

他们都是用了Widget_Metas_Category_List组件。我们只需要把这个组件里的分类数据读取出来自己输出就好了,还是模板和数据分类的问题。

首先我们在模板里读取分类数据存储到$categories,然后对他进行循环输出即可。通过阅读Widget_Metas_Category_list的源代码,写出了下面这段代码来输出categories,只要用它替换上面哪行listCategories或者parse调用即可

<?php $this->widget('Widget_Metas_Category_List')->to($category); ?>
<?php if ($category->have()): ?>
<?php while ($category->next()): ?>
    <?php if ($category->levels == 0): ?>
        <?php $children = $category->getAllChildren($category->mid); ?>
        <?php if (empty($children)) :?>
            <li><a href="<?php $category->permalink() ?>"> <?php $category->name() ?></a></li>
        <?php else : ?>
            <li class="dropdown">
                <a href="<?php $category->permalink() ?>" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php $category->name() ?><span class="caret"></span></a>
                <ul class="dropdown-menu">
                    <?php foreach ($children as $child ): ?>
                        <?php $child = $category->getCategory($child) ?>
                        <li class=""><a href="<?php echo $child['permalink']; ?>"> <?php echo $child['name']; ?></a></li>
                    <?php endforeach ?>
                </ul>
            </li>
        <?php endif ?>
    <?php endif ?>
<?php endwhile; ?>
<?php endif ?>

到此,功能需求达成。上张图吧
WeChat Screenshot_20180823122738.png

后续吐槽

对于分类golang

$children = $category->getAllChildren($category->mid);

这行代码得到$children为

/usr/themes/TypeD8/header.php:44:
array (size=2)
  0 => int 29
  1 => int 30
Golang

很好理解golang分类有两个子分类,29和30。

接着我们用for循环去处理这两个子分类,对于29号子分类。

$child = $category->getCategory($child);

我们得到了什么?

array (size=14)
  'mid' => string '29' (length=2)
  'name' => string 'GO网络编程' (length=14)
  'slug' => string 'GO网络编程' (length=14)
  'type' => string 'category' (length=8)
  'description' => string '本分类为Network Programming With Go读书笔记以及代码实验' (length=69)
  'count' => string '0' (length=1)
  'order' => string '1' (length=1)
  'parent' => string '8' (length=1)
  'levels' => int 1
  'directory' => 
    array (size=2)
      0 => string 'Golang' (length=6)
      1 => string 'GO网络编程' (length=14)
  'permalink' => string 'http://blog.shyclouds.net/category/GO%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/' (length=74)
  'feedUrl' => string 'http://blog.shyclouds.net/feed/category/GO%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/' (length=79)
  'feedRssUrl' => string 'http://blog.shyclouds.net/feed/rss/category/GO%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/' (length=83)
  'feedAtomUrl' => string 'http://blog.shyclouds.net/feed/atom/category/GO%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/' (length=84)

EXECUSE ME? 为什么感觉设计如此蹩脚?一级分类列表循环处理的时候可是对象:

$category->name()
$category->permalink()

为何到了二级分类就成了数组了?

$child['name']
$child['permalink']

这种严重的不一致表现,是我做法不对,还是作者遇到了什么问题么?回头我深入研究下Widget循环实现吧。

打赏

微信打赏

支付宝打赏



与本文相关的文章

网友最新评论( 4 )

那问哈大神,你这个可以直接用了吗?看你最后说遇到问题了。

May 15th, 2019
Sun

我之前试过无限分类,然后放弃。比如说 主分类 二级分类1 二级分类2 二级分类子分类1 二级分类子分类2 二级分类子分类1子分类1 二级分类子分类1子分类2 .....这样子多达将近50个大类 100多个二级分类 两千多二级分类子分类 剩下的不说了~

July 31st, 2020
发表我的评论
昵称 (必填)
邮箱 (必填)
网址
执行时间: 1733648645628.4 毫秒