1. Bug 现象描述
在将 Typecho 博客程序升级到最新版本 1.3.x 后,使用 Joe 主题时,顶部和侧边栏的独立页面导航菜单(例如“瞬间”、“留言板”、“关于”等)链接集体失效。具体表现为:所有独立页面的链接全部变成了网站的首页地址,点击后仅会刷新跳转回首页,无法正常访问相应的独立页面。
2. 问题原因分析
该 Bug 的核心原因在于 Joe 主题获取页面列表数据的语法在 Typecho 1.3 版本中由于核心更新而失效。
为了实现后台设置的“导航菜单最大显示数量(JNavMaxNum)”以及超出后的“更多”下拉菜单功能,Joe 主题的原作者在代码中没有采用 Typecho 官方标准的迭代方法,而是直接提取了组件底层的原始数据源集合(即 $pages->stack)进行 foreach 循环。
代码差异导致的问题:
在 Typecho 1.2.1 及更早版本中,$pages->stack 数组在初始化时直接持有了 permalink(固定链接)等属性,所以直接获取 $item['permalink'] 碰巧是有效的。
然而,在 Typecho 1.3 的代码更新中,permalink、slug 等依赖路由解析的衍生属性调整为了动态加载。如果未调用官方数据解析接口 $pages->next() ,而是强行绕过 API 直接读取底层数组 $item['permalink'],将无法获取正确解析后的链接,导致返回值为空。最终,前端的 HTML href 属性输出异常,被浏览器默认解析为了网站根目录(首页)。
3. 完美修复方案
要解决这个问题,我们需要兼顾 Joe 主题的“数量限制与折叠”功能,同时严格遵循 Typecho 的官方规范。只需通过 $pages->next() 接口先行安全遍历数据,将其转存到一个新数组中,再对新数组进行逻辑切片和输出即可。这不仅能完美修复 1.3 下的 Bug,同时代码也能向下兼容老版本。
修复步骤详解
请在你的 Joe 主题源码目录中,找到并打开 public/header.php 文件。
第一步:修复顶部 PC 端导航
在 header.php 文件中找到第 84 行附近(顶部导航输出区域):
修改前:
<?php $this->widget('Widget_Contents_Page_List')->to($pages); ?>
<?php if (count($pages->stack) <= $this->options->JNavMaxNum) : ?>
<?php foreach ($pages->stack as $item) : ?>修改后:
<?php
$this->widget('Widget_Contents_Page_List')->to($pages);
// 【新增】安全解析:使用标准 API 取出并构建完整页面属性数组
$pageItems = [];
while ($pages->next()) {
$pageItems[] = [
'slug' => $pages->slug,
'permalink' => $pages->permalink,
'title' => $pages->title
];
}
?>
<?php if (count($pageItems) <= $this->options->JNavMaxNum) : ?>
<?php foreach ($pageItems as $item) : ?>注意: 替换完毕后,请紧接着将该判断逻辑下方所有的 $pages->stack 都替换为我们刚刚构建好的 $pageItems。例如,原来代码中的 array_slice($pages->stack, ...) 需要统一修改为 array_slice($pageItems, ...)。
第二步:修复侧边栏 / 移动端导航
在同一个 header.php 文件中继续向下寻找,定位到第 378 行附近(侧边栏页面列表输出区域):
修改前:
<ul class="slides panel-body">
<?php foreach ($pages->stack as $item) : ?>
<li>
<a class="link <?php echo $this->is('page', $item['slug']) ? 'current' : '' ?>" href="<?php echo $item['permalink'] ?>" title="<?php echo $item['title'] ?>"><?php echo $item['title'] ?></a>
</li>
<?php endforeach; ?>
</ul>修改后(直接将 $pages->stack 替换为 $pageItems 即可):
<ul class="slides panel-body">
<?php foreach ($pageItems as $item) : ?>
<li>
<a class="link <?php echo $this->is('page', $item['slug']) ? 'current' : '' ?>" href="<?php echo $item['permalink'] ?>" title="<?php echo $item['title'] ?>"><?php echo $item['title'] ?></a>
</li>
<?php endforeach; ?>
</ul>4. 完成
保存对 header.php 的修改,刷新你的博客。测试点击顶部的“留言板”等独立页面,你就会发现熟悉且正常的导航功能又回来啦!
评论 (0)