1. 首页
  2. >
  3. 前端技术
  4. >
  5. Typecho

文章分类 listCategories 函数隐藏未启用条目

添加评论

近期给博客更新主题功能时,在边栏显示文章分类环节遇到了个小困扰。我使用的是官方默认主题提供的 listCategories(); 函数,它能正常输出所有分类,但由于我的“强迫症”原因,提前预留了 100 个分类,目的是防止后续标签占用数据表而导致分类 ID 隔断不连续,但这就出现了一个明显问题:该函数会把未启用的分类也一并列出。

函数效果

原函数展示效果

改进思路

查阅官方文档和网上的解决方案后,发现多数思路是将所有分类压入数组,再通过重组数组元素剔除未使用的分类。但这个方案并不适合我的主题,我将主题诸多功能都集成在 functions.php 中,文件内已有大量代码,若新增分类处理逻辑以及多级菜单的生成,会进一步降低代码可读性不便于后续维护,所以我的核心诉求很明确:在不改动核心源码、精简情况下进行改进

处理方式

在调用 listCategories(); 前,使用 ob_start(); 捕获内容至缓冲区,再通过ob_get_clean(); 将缓冲区内容取出并赋值给变量。
这里必须注意:要将 listCategories();showCount 参数开启,这是后续匹配空分类的关键依据。

PHP
  1. ob_start();
  2. \Widget\Metas\Category\Rows::alloc()->listCategories([
  3. 'wrapClass' => 'widget-categories',
  4. 'showCount' => true,
  5. 'countTemplate' => '<span class="count">%d</span>'
  6. ]);
  7. $base = ob_get_clean();

空分类的核心特征是 count 标签内的数值为 0,我是通过两段正则,分别实现“删除空分类列表项”和“清理空分类对应的子菜单”:

PHP
  1. // 删除空分类
  2. do {
  3. $cache = $base;
  4. $base = preg_replace('#<li[^>]*>(?:(?!<li).)*?<([a-zA-Z0-9]+)\s+class="count">0</\1>(?:(?!<li).)*?</li>\s*#is', '', $base);
  5. } while ( $cache !== $base );
  6.  
  7. // 整个分类均为空,则删除整个子菜单
  8. $base = preg_replace('#<ul\b[^>]*>(?:\s|&nbsp;|<!--.*?-->)*</ul>\s*#is', '', $base );

正则说明:

  1. 第一段正则中:(?:(?!<li).)*? 是负向预查,确保只匹配当前 li 标签内的内容,不跨层级匹配子元素。
  2. 第二段正则用于清理空 ul 容器,如果该子分类所有的 li 均移除,则删除空 ul 子菜单。

总结与拓展思路

本次优化的核心优势在于,没有改动主题核心源码和 listCategories(); 函数本身,仅通过“缓冲区捕获 + 正则过滤”的组合,就解决了未启用分类显示的问题。当然也可以在前端通过 jQuery / Zepto 等框架交给客户端处理。
不过,对于我所需要简单的分类列表结构,本次的正则方案已经足够高效。如果你的博客分类存在多层级嵌套、结构复杂的情况,建议尝试DOMDocument 解析方案,稳定性会更有保障。

文章分类 listCategories 函数隐藏未启用条目
https://www.uevan.com/listcategories-hide-inactive-items
文章作者
许可协议
CC BY-NC 4.0
转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!
  1. 暂无评论
浏览记录
  • 暂无记录