使用 {dede:channel} 标签(最常用、最推荐)
这是最标准、最织梦化的方法,适用于大多数场景,尤其是在首页、列表页等模板文件中。

(图片来源网络,侵删)
基本原理
{dede:channel} 标签用于获取栏目列表,通过设置其 typeid 和 reid 属性,我们可以精确地获取指定一级栏目下的所有二级栏目。
typeid: 指定一级栏目的 ID。reid: 指定父级栏目的 ID,当typeid和reid同时使用时,typeid会被忽略,reid生效。type: 设置son或topson可以获取子栏目。son获取直接子栏目,topson获取所有下级栏目(包括孙级等)。
实际操作步骤
假设我们要获取 ID 为 1 的一级栏目(产品中心”)下的所有二级栏目。
在模板文件中使用标签
在你需要显示二级栏目的地方(index.htm 或 product_list.htm),使用以下代码:

(图片来源网络,侵删)
<h2>产品分类</h2>
<ul>
{dede:channel type='son' reid='1'}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
</li>
{/dede:channel}
</ul>
代码解析:
{dede:channel type='son' reid='1'}reid='1': 这是最关键的部分,它告诉 DedeCMS “请找到父栏目 ID 为 1 的所有子栏目”。type='son': 明确表示只获取直接子栏目(即二级栏目),如果不加type属性,默认行为也是获取直接子栏目,但加上可以更清晰。
[field:typelink/]: 输出栏目的完整链接地址,/a/products/computer/。[field:typename/]: 输出栏目的名称,电脑产品”。
如果二级栏目下还有三级栏目,如何获取?
如果二级栏目“电脑产品”下还有“笔记本”、“台式机”等三级栏目,并且想在二级栏目列表后面也显示出来,可以使用嵌套标签。
<h2>产品分类</h2>
<ul>
{dede:channel type='son' reid='1'}
<li>
<!-- 二级栏目名称和链接 -->
<a href="[field:typelink/]">[field:typename/]</a>
<!-- 判断该二级栏目下是否有子栏目(三级栏目) -->
{dede:field name='typeid' function='GetSonIds(@me)'/}
{if $fields.str != ''}
<ul>
<!-- 如果有,则循环输出三级栏目 -->
{dede:channel type='son' reid='[field:id/]'}
<li><a href="[field:typelink/]">[field:typename/]</a></li>
{/dede:channel}
</ul>
{/if}
</li>
{/dede:channel}
</ul>
代码解析:
{dede:field name='typeid' function='GetSonIds(@me)'/}: 这是一个自定义函数调用。@me代表当前栏目的 ID。GetSonIds()是 DedeCMS 的一个内置函数,它会返回指定栏目 ID 的所有下级栏目 ID,并以逗号连接成一个字符串。- 我们把这个结果存入变量
$fields.str。
{if $fields.str != ''}: 判断$fields.str是否为空,如果不为空,说明该二级栏目下还有子栏目(三级或更多)。- 内层的
{dede:channel type='son' reid='[field:id/]'/}: 循环输出当前二级栏目下的所有三级栏目。[field:id/]在这里获取的是当前二级栏目的 ID。
使用自定义 SQL 查询(更灵活、更强大)
当 {dede:channel} 标签无法满足复杂需求时(需要获取多个不同一级栏目下的二级栏目,并进行特殊排序或筛选),可以直接在模板中使用 SQL 查询。
基本原理
通过 dede_arctype 表来查询栏目信息。reid 字段存储了父栏目的 ID,topid 字段存储了顶级栏目的 ID。
实际操作步骤
假设我们要获取顶级栏目 ID 为 1 的所有二级栏目,并按 sortrank 排序。
在模板文件中使用 {dede:sql}
<h2>产品分类 (SQL版)</h2>
<ul>
{dede:sql sql="SELECT id, typename, typelink FROM dede_arctype WHERE reid=1 AND ishidden<>1 ORDER BY sortrank ASC"}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
</li>
{/dede:sql}
</ul>
代码解析:
{dede:sql sql="..."}: 执行自定义 SQL 语句。SELECT id, typename, typelink FROM dede_arctype: 从dede_arctype表中选择需要的字段。typelink字段是 DedeCMS 自动生成的完整链接,非常方便。WHERE reid=1: 这是查询的核心条件,reid=1表示只查找父栏目 ID 为 1 的所有栏目(即二级栏目)。AND ishidden<>1: 这是一个常用的条件,排除掉在后台设置为“隐藏”的栏目。ORDER BY sortrank ASC: 按后台设置的“排序值”进行升序排列。[field:typename/]和[field:typelink/]: 和{dede:channel}标签中一样,用于输出查询结果中的字段。
获取多个顶级栏目下的二级栏目
如果需要同时获取顶级 ID 为 1 和 2 的所有二级栏目:
{dede:sql sql="SELECT id, typename, typelink FROM dede_arctype WHERE topid IN (1, 2) AND reid<>0 AND ishidden<>1 ORDER BY sortrank ASC"}
...
{/dede:sql}
WHERE topid IN (1, 2):topid是顶级栏目的 ID,这个条件表示查找顶级栏目是 1 或 2 的所有栏目。AND reid<>0: 加上这个条件是为了确保我们获取的是二级或更深的栏目,而不是顶级栏目本身。
在 PHP 文件中获取(用于二次开发)
如果你需要在 PHP 文件(例如自定义的控制器、模型或函数)中获取二级栏目数据,可以直接调用 DedeCMS 的底层类。
基本原理
实例化 DedeClass 中的 TypeLink 类,或者直接使用 GetSonIds 等函数。
实际操作步骤
<?php
require_once(dirname(__FILE__)."/include/common.inc.php"); // 引入核心文件
// 方法一:使用 GetSonIds 函数获取所有二级栏目ID
$parent_id = 1; // 假设一级栏目ID为1
$son_ids = GetSonIds($parent_id); // 返回如 "3,4,5" 的字符串
// 将字符串转换为数组
$son_id_array = explode(',', $son_ids);
// 方法二:使用 TypeLink 类获取更详细的栏目信息
$dsql = new DedeSql(false);
$typelink = new TypeLink($dsql);
// 获取指定ID的栏目信息
$topType = $typelink->GetOneType($parent_id);
// 获取其所有子栏目
$son_types = $typelink->GetSonIds($topType, 0, false);
// 遍历输出
echo "<ul>";
foreach($son_types as $type) {
echo "<li>";
echo "<a href='".$type['typelink']."'>".$type['typename']."</a>";
echo "</li>";
}
echo "</ul>";
// 关闭数据库连接
$dsql->Close();
?>
总结与对比
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
{dede:channel} |
最简单、最标准,符合 DedeCMS 设计理念,无需写 SQL。 | 灵活性相对较差,嵌套使用时标签结构会变复杂。 | 绝大多数场景,如首页、列表页、内容页的栏目调用。 |
{dede:sql} |
非常灵活,可以任意组合查询条件,实现复杂逻辑。 | 需要了解 SQL 语法,对新手有一定门槛。 | 需要复杂筛选、排序或调用多个不同栏目数据时。 |
| PHP 代码调用 | 功能最强大,可以结合 PHP 逻辑进行复杂处理。 | 需要二次开发能力,不适合在模板文件中直接使用。 | 自定义模块、插件或功能扩展时。 |
对于日常的模板制作,强烈推荐使用方法一 {dede:channel},它是最符合 DedeCMS 使用习惯且最高效的方式。
