- 一级栏目 (ID=1)
- 二级栏目A (ID=2)
- 三级栏目A1 (ID=5)
- 二级栏目B (ID=3)
- 三级栏目B1 (ID=6)
- 一级栏目 (ID=4)
- 二级栏目C (ID=7)
当你访问 三级栏目A1 (ID=5) 的页面时,"当前栏目"是ID=5,调用它的"二级栏目"应该是指它的直接上级栏目 二级栏目A (ID=2)。

但通常大家所说的“调用当前栏目的二级栏目”,其实是想表达:“获取当前栏目所属的顶级栏目下的所有直接子栏目”,在上面的例子中,无论你访问三级栏目A1、二级栏目A,甚至是顶级栏目1,调出的结果都应该是 [二级栏目A, 二级栏目B]。
下面我将为你提供最常用和最推荐的几种方法,并解释其原理。
使用 {dede:channel} 标签(最常用、最推荐)
这是最灵活、最标准的方法,它通过获取当前顶级栏目的ID,然后调用该ID下的所有子栏目。
核心思路:

- 使用
{dede:field.typeid/}获取当前栏目的ID。 - 使用
{dede:php}...{/dede:php}标签,通过GetTopid()函数向上查找,获取当前栏目所属的顶级栏目的ID。 - 将获取到的顶级栏目ID,作为
{dede:channel}标签的reid(父级ID)参数,进行子栏目调用。
完整代码示例:
{dede:channel type='son' noself='yes'}
<a href="[field:typelink/]">[field:typename/]</a>
{/dede:channel}
代码解释:
{dede:channel type='son' noself='yes'}type='son': 指定调用类型为“子栏目”。noself='yes': 非常重要,表示不调用栏目本身,如果不加,当你在顶级栏目页时,会调用出顶级栏目自己,这不是我们想要的结果。reid='0': 这是调用顶级栏目的关键,但我们不直接写死ID,而是通过PHP动态获取。
将上述代码放入你的模板文件中即可,它会自动工作。
更详细的写法(便于理解):

如果你想把每一步都写出来,可以这样,虽然冗余,但逻辑更清晰:
{dede:php}
// 获取当前顶级栏目的ID
$topid = GetTopid($refObj->TypeLink->TypeInfos['id']);
// 将ID赋值给一个变量,供下面的channel标签使用
$GLOBALS['topid'] = $topid;
{/dede:php}
{dede:channel type='son' reid='~topid~' noself='yes'}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
</li>
{/dede:channel}
注意:在这种写法中,reid 的值需要写成 ~topid~,这是DedeCMS在模板中调用PHP变量的特殊语法。
使用 {dede:arclist} 标签(特定场景下使用)
这种方法主要用于在列表页或内容页,调用当前顶级栏目下的文章列表,虽然它不直接调用栏目,但能实现“在当前栏目下显示其兄弟栏目(即同级的二级栏目)”的类似效果。
适用场景: 你希望在当前栏目的页面(列表页或内容页)上,显示一个“同级别推荐栏目”的列表,并附带每个栏目的最新文章。
代码示例:
{dede:arclist typeid='~topid~' row='10' titlelen='30'}
<a href="[field:arcurl/]">[field:title/]</a>
{/dede:arclist}
代码解释:
typeid='~topid~': 这里的~topid~同样是通过{dede:php}标签中的GetTopid()函数获取的当前顶级栏目ID。typeid指定了文章列表的栏目范围。row='10': 显示10条文章,len='30'`: 标题长度限制为30个字符。
使用此方法的前提是:
你必须在模板的 {dede:php} 部分正确获取并设置了 $topid 变量。
使用SQL直接查询(最灵活,但需注意安全)
如果你对SQL比较熟悉,并且需要非常复杂的自定义条件,可以直接在模板中执行SQL查询。
核心思路:
- 同样,先用PHP获取当前顶级栏目的ID。
- 编写SQL语句,从
dede_arctype表中查询topid等于该ID的所有栏目。
代码示例:
{dede:php}
// 1. 获取当前顶级栏目ID
$topid = GetTopid($refObj->TypeLink->TypeInfos['id']);
// 2. 准备SQL查询
$sql = "SELECT id, typename, typedir FROM `dede_arctype` WHERE topid = $topid ORDER BY id";
// 3. 执行查询
$dsql->SetQuery($sql);
$dsql->Execute();
// 4. 循环输出结果
while($row = $dsql->GetArray())
{
echo '<a href="'.$row['typedir'].'/">'.$row['typename'].'</a>';
}
{/dede:php}
代码解释:
GetTopid(): 获取顶级ID。$sql: SQL查询语句,dede_arctype是DedeCMS的栏目表。topid字段存储了每个栏目的顶级栏目ID。ORDER BY id: 按栏目ID排序,你可以根据需要改为orders字段来按照后台设置的排序显示。$dsql->SetQuery()和$dsql->Execute(): 执行SQL。while($row = $dsql->GetArray()): 循环获取查询结果并输出。
⚠️ 安全警告:
直接在模板中拼接SQL有SQL注入的风险,虽然 $topid 来自系统函数,相对安全,但最佳实践是使用 $dsql->GetOne() 或 $dsql->Execute() 的参数绑定功能,不过对于这个由系统内部生成的ID,直接使用通常也是安全的。
总结与推荐
| 方法 | 优点 | 缺点 | 推荐度 |
|---|---|---|---|
{dede:channel} |
代码简洁、高效、安全,符合DedeCMS设计规范 | 理解上需要一点PHP基础(GetTopid函数) |
⭐⭐⭐⭐⭐ (强烈推荐) |
{dede:arclist} |
适合调用文章,功能强大 | 仅限文章列表,不直接调用栏目结构 | ⭐⭐⭐ |
| SQL查询 | 极度灵活,可以实现任何自定义需求 | 代码复杂,有潜在安全风险,不易维护 | ⭐⭐ |
对于99%的需求,直接使用方法一 就完全足够了,它是最标准、最健壮、也是最容易维护的解决方案,只需在你的模板文件中,需要显示子栏目的位置,粘贴方法一的代码即可。
