实现这个功能主要有两种方法,一种是简单直接的,另一种是更完善的,推荐使用第二种。
场景说明
假设我们有以下栏目结构:
- 产品中心 (父栏目,ID=1)
- 手机系列 (子栏目,ID=2)
- 电脑系列 (子栏目,ID=3)
- 配件系列 (子栏目,ID=4)
默认情况下,点击“产品中心”可能会指向一个自定义的页面(如 plus/list.php?tid=1),这个页面可能为空或者显示“产品中心”这个栏目的文章,但我们希望点击“产品中心”时,直接跳转到它的第一个子栏目(如“手机系列”)的列表页。
修改数据库(简单直接但不推荐)
这种方法最简单,但不够灵活,如果栏目结构改变,你需要手动再次修改。
-
登录你的网站后台。
-
进入【系统】-> SQL命令行工具。
-
在“运行SQL文件”的文本框中,输入以下代码(请将
1替换为你父栏目的ID):UPDATE dede_arctype SET typedir = (SELECT typedir FROM dede_arctype WHERE reid = 1 AND isdefault = 1 ORDER BY id ASC LIMIT 1) WHERE id = 1;
代码解释:
UPDATE dede_arctype SET ... WHERE id = 1:这是要更新的目标表(dede_arctype)和目标栏目(ID为1的“产品中心”)。typedir = ...:我们要更新的是栏目的链接地址(typedir字段)。(SELECT typedir FROM dede_arctype WHERE reid = 1 AND isdefault = 1 ORDER BY id ASC LIMIT 1):这是查询出来的值。reid = 1:查找父栏目ID为1的所有子栏目。isdefault = 1:确保找到的是“默认”的子栏目(通常创建时默认勾选)。ORDER BY id ASC LIMIT 1:按子栏目ID排序并只取第一个,确保结果稳定。
WHERE id = 1:更新的是ID为1的父栏目。
-
点击【确定】执行。
缺点:
- 硬编码:如果父栏目ID或子栏目结构发生变化,这个SQL语句需要重新执行。
- 不灵活:如果父栏目下没有子栏目,这个操作会出错。
修改PHP模板文件(推荐,更灵活、更规范)
这是更推荐的方法,它通过修改模板文件来动态实现这个逻辑,无需频繁操作数据库。
步骤 1:修改 include/typelink.class.php 文件
这个文件是处理栏目链接的核心类文件,我们需要修改它,让它能自动判断并返回子栏目的链接。
-
用FTP或文件管理器打开
/include/typelink.class.php文件。 -
找到
TypeLink类中的GetOneTypeLink($typeid)方法。 -
在这个方法的开头,添加一段判断逻辑,在类似
global $dsql;的下面,添加如下代码:// 检查当前栏目是否有下级子栏目 $hasChild = false; $query = "SELECT id FROM dede_arctype WHERE reid = '$typeid' AND ishidden <> 1 LIMIT 1"; $dsql->Execute('me', $query); if ($dsql->GetTotalRow('me') > 0) { $hasChild = true; } // 如果有子栏目,则获取第一个子栏目的链接 if ($hasChild) { $query = "SELECT id,typedir FROM dede_arctype WHERE reid = '$typeid' AND ishidden <> 1 ORDER BY id ASC LIMIT 1"; $row = $dsql->GetOne($query); if (is_array($row)) { $typepage = GetTypeUrl($row['id'], MfTypedir($row['typedir']), $row['isdefault'], $row['defaultname'], $row['ispart'], $row['namerule'], $row['typedir'], $row['moresite'], $row['siteurl'], $row['sitepath']); return $typepage; } }代码解释:
- 首先查询当前栏目(
$typeid)下是否存在非隐藏的子栏目。 - 如果存在,则再次查询,获取第一个子栏目的完整信息(ID,
typedir等)。 - 调用
GetTypeUrl()函数,根据子栏目的信息生成标准的栏目链接。 return $typepage;直接返回子栏目的链接,覆盖了原来要返回的父栏目链接。
- 首先查询当前栏目(
-
保存并上传修改后的
typelink.class.php文件。
步骤 2:修改模板文件(如 head.htm)
当你在模板中调用栏目链接时,它会自动返回子栏目的链接了,我们以网站顶部导航栏为例。
-
打开你的模板文件,通常是
/templets/default/head.htm或你自定义的模板文件。 -
找到调用栏目的地方,通常是使用
{dede:channel}或{dede:global name='itemindex'/}的循环。 -
在
<a>标签的href属性中,使用{dede:field name='typeurl'/}来获取栏目链接。修改前(可能的样子):
<li><a href='{dede:field name='typeurl'/}'>{dede:field name='typename'/}</a></li>修改后(的样子,无需改动代码,因为
typeurl的行为已经被我们改变了):<li><a href='{dede:field name='typeurl'/}'>{dede:field name='typename'/}</a></li>注意: 你不需要修改模板文件中的代码本身,因为
{dede:field name='typeurl'/}这个标签在调用时,会触发我们刚刚修改的GetOneTypeLink方法,对于有子栏目的父栏目,typeurl会自动指向第一个子栏目。
步骤 3:清除缓存
修改完文件后,一定要清除 DedeCMS 的缓存,否则看不到效果。
- 在后台进入【系统】-> 一键更新网站。
- 勾选“更新HTML”、“更新栏目”等,然后点击“开始更新”,这一步会自动清除缓存。
总结与对比
| 特性 | 方法一(修改数据库) | 方法二(修改PHP文件) |
|---|---|---|
| 优点 | 简单快速,无需理解代码逻辑 | 灵活、动态,栏目结构改变后无需手动修改 |
| 缺点 | 硬编码、不灵活,维护麻烦,易出错 | 需要修改核心文件,有一定技术门槛 |
| 推荐度 | ⭐☆☆☆☆ (不推荐) | ⭐⭐⭐⭐⭐ (强烈推荐) |
强烈建议使用方法二,虽然它需要你修改一个核心的PHP文件,但它是一次性的修改,并且非常健壮和灵活,它能完美适应未来可能发生的栏目结构调整,是解决此问题的最佳实践。
