背景介绍
先来说说当前的菜单样式吧
- 系统默认菜单栏实现和样式
// 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的人)
显示效果呢,上个图吧
-
再来看看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。显示效果如下图
这就搞笑了,父分类和子分类显示在了同一个层级上。我本以为子分类会不显示的,毕竟我还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 ?>
到此,功能需求达成。上张图吧
后续吐槽
对于分类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循环实现吧。
那问哈大神,你这个可以直接用了吗?看你最后说遇到问题了。
我之前试过无限分类,然后放弃。比如说 主分类 二级分类1 二级分类2 二级分类子分类1 二级分类子分类2 二级分类子分类1子分类1 二级分类子分类1子分类2 .....这样子多达将近50个大类 100多个二级分类 两千多二级分类子分类 剩下的不说了~