handsome的主题支持设置指定分类在首页显示隐藏,但是有一个问题就是我一个文章同时设置了分类A、分类B,其中分类A不显示,分类B显示,结果首页还是显示了,其实我想只要有这个分类就不要显示。比如胡东东博客的折腾分类,内容很杂,但是不希望在首页显示。

排查之后这个功能并不是在主题,而是在配套的handsome插件功能里,所以需要修改usr/plugins/Handsome/Plugin.php文件。

原因

原因是查询语法的问题,文章如果同时包含“隐藏分类A”和“可见分类B”,它在关系表中有两条记录(mid=A 和 mid=B)。 当前查询对每个隐藏分类ID都加了一个 mid != 该ID 的条件(多个条件之间是 AND 关系),这会导致:

  • 对于 mid=A 的记录,它不满足 mid != A,所以被过滤掉;
  • 但对于 mid=B 的记录,它满足 mid != A,于是被保留下来。

加上最后用了 GROUP BY cid,只要有一条记录被保留,这篇文章就会出现在结果集中——所以它仍然显示在首页。

修改

typecho的1.2版本Sql解析不支持NOT IN的解析,所以需要修改内核文件var/Typecho/Db/Query.php,支持一下NOT字段

//原内容
//private const KEYWORDS = '*PRIMARY|AND|OR|LIKE|ILIKE|BINARY|BY|DISTINCT|AS|IN|IS|NULL';

//增加NOT
private const KEYWORDS = '*PRIMARY|AND|OR|LIKE|ILIKE|BINARY|BY|DISTINCT|AS|IN|NOT|IS|NULL';

之后修改usr/plugins/Handsome/Plugin.php文件的CateFilter功能,第1127行首页不显示分类隐藏的内容的代码,替换为

//首页不显示分类隐藏的内容
$CateIds = Typecho_Widget::widget('Widget_Options')->plugin('Handsome')->CateId;
if (!$CateIds) return $select; 

// 1. 清理和格式化分类 ID 数组
$CateIds = explode(',', $CateIds);
$CateIds = array_map('intval', $CateIds); 
$CateIds = array_filter($CateIds);        
$CateIds = array_unique($CateIds);        

if (empty($CateIds)) return $select;

// 2. 利用底层最轻量的单独查询,把这几个隐藏分类下的所有文章 cid 先捞出来
$db = Typecho_Db::get();
$rows = $db->fetchAll($db->select('cid')
    ->from('table.relationships')
    ->where('mid IN ?', $CateIds));

// 3. 提取出单纯的一维数字数组 [12, 15, 23 ...]
$hideCids = array_column($rows, 'cid');

// 4. 过滤
if (!empty($hideCids)) {
    $select = $select->where('table.contents.cid NOT IN ?', $hideCids);
}

return $select;
最后修改:2026 年 07 月 07 日
请我喝杯可乐,请随意打赏: ☞已打赏列表