使用 {dede:channel} 标签(最常用、最推荐)
这是 DedeCMS 最核心、最灵活的分类调用标签,适用于绝大多数场景。

(图片来源网络,侵删)
基础调用:只调用顶级分类
如果你只想显示网站所有的一级(顶级)分类,可以使用以下代码:
{dede:channel type='top'}
<a href="[field:typeurl/]">[field:typename/]</a>
{/dede:channel}
type='top': 这是关键参数,表示只调用顶级栏目。[field:typeurl/]: 调用栏目的链接地址。[field:typename/]: 调用栏目的名称。
高级调用:调用所有分类(包括子分类)
这是最接近“全部分类”需求的实现,即同时显示顶级分类和它们各自的子分类,这通常需要结合 {dede:channel} 和 {dede:channelartlist} 或嵌套的 {dede:channel} 来实现。
方案A:使用 {dede:channelartlist}(推荐,结构清晰)
这个标签专门用于调用顶级栏目及其下的子栏目,生成的HTML结构非常适合制作导航栏。
{dede:channelartlist typeid='0'}
<div class="mainnav">
<h3><a href="{dede:field name='typeurl'/}">{dede:field name='typename'/}</a></h3>
<div class="subnav">
<ul>
{dede:channel type='son' noself='yes'}
<li><a href="[field:typeurl/]">[field:typename/]</a></li>
{/dede:channel}
</ul>
</div>
</div>
{/dede:channelartlist}
代码解析:
{dede:channelartlist typeid='0'}:typeid='0'表示调用所有顶级栏目。- 这个标签会循环遍历每一个顶级栏目。
<h3><a href="{dede:field name='typeurl'/}">{dede:field name='typename'/}</a></h3>:- 在循环内部,
{dede:field}用于获取当前顶级栏目的信息。 name='typeurl'获取顶级栏目的链接。name='typename'获取顶级栏目的名称。
- 在循环内部,
{dede:channel type='son' noself='yes'}:- 这个标签嵌套在
{dede:channelartlist}内部,因此它会在每个顶级栏目的循环中执行一次。 type='son'是关键,表示只调用当前顶级栏目下的子栏目。noself='yes'表示不调用栏目本身,只调用子栏目,避免重复显示顶级栏目名称。
- 这个标签嵌套在
[field:typeurl/]和[field:typename/]:- 这里使用的
field变量是{dede:channel}标签的,它指向的是当前循环到的子栏目的信息。
- 这里使用的
方案B:使用嵌套的 {dede:channel}(更灵活,但需手动处理层级)
如果你对HTML结构有完全的控制权,可以使用这种方法。
<ul class="top-category">
{dede:channel type='top'}
<li>
<a href="[field:typeurl/]">[field:typename/]</a>
{dede:channel type='son' row='8' noself='yes'}
<a href="[field:typeurl/]">[field:typename/]</a>
{/dede:channel}
</li>
{/dede:channel}
</ul>
代码解析:
- 外层的
{dede:channel type='top'}循环所有顶级分类。 - 内层的
{dede:channel type='son'}在每个顶级分类的<li>内部,循环调用其子分类。 row='8'可以限制显示的子分类数量。
使用SQL直接查询(适用于复杂需求或模板中无法使用标签时)
如果你需要更复杂的筛选、排序或者对数据进行二次处理,可以直接在模板中执行SQL查询。
调用所有顶级分类
{dede:sql sql='SELECT id,typename,typedir FROM `dede_arctype` WHERE reid=0 ORDER BY id'}
<a href="[field:typedir function='MakeOneDir(@me)'/]">[field:typename/]</a>
{/dede:sql}
代码解析:
sql='...': 这里是标准的SQL查询语句。dede_arctype: DedeCMS中存储栏目的表名(你的表前缀可能是#@_,请根据实际情况修改)。reid=0:reid字段表示父栏目的ID,reid=0就是顶级分类。ORDER BY id: 按栏目ID排序。
[field:typedir function='MakeOneDir(@me)'/]:typedir字段存储的是相对路径,MakeOneDir是DedeCMS内置的函数,用于将其转换为完整的URL。
调用所有分类(包括顶级和子分类)
{dede:sql sql='SELECT id,typename,typedir,reid FROM `dede_arctype` ORDER BY reid,id'}
{if $fields.reid == 0}
<!-- 这是顶级分类 -->
<div class="top-category">
<h3>[field:typename/]</h3>
<ul>
{else}
<!-- 这是子分类 -->
<li><a href="[field:typedir function='MakeOneDir(@me)'/]">[field:typename/]</a></li>
{/if}
<!-- 循环结束后关闭顶级分类的标签 -->
{dede:sql sql='SELECT id,reid FROM `dede_arctype` ORDER BY id desc limit 1'}
{if $fields.reid != 0}</ul></div>{/if}
{/dede:sql}
{/dede:sql}
注意:这种方法比较复杂,需要手动处理HTML标签的开闭,容易出错。强烈推荐使用方法一中的 {dede:channelartlist},它在设计上就是为了解决这种需求。
使用自定义函数(PHP代码)
如果以上方法都无法满足你的需求,或者你需要一个非常复杂的、可复用的分类列表,你可以在 /include/helpers/extend.helper.php 文件中添加一个自定义函数,然后在模板中调用。
在 extend.helper.php 中添加函数
if ( ! function_exists('GetAllCategories'))
{
function GetAllCategories($topid = 0)
{
global $dsql;
$categories = array();
// 获取顶级分类
$topQuery = "SELECT id, typename, typedir FROM `dede_arctype` WHERE reid=0 ORDER BY id";
$dsql->Execute('top', $topQuery);
while ($topRow = $dsql->GetArray('top')) {
$topRow['children'] = array();
// 获取子分类
$sonQuery = "SELECT id, typename, typedir FROM `dede_arctype` WHERE reid={$topRow['id']} ORDER BY id";
$dsql->Execute('son', $sonQuery);
while ($sonRow = $dsql->GetArray('son')) {
$topRow['children'][] = $sonRow;
}
$categories[] = $topRow;
}
return $categories;
}
}
在模板中调用
{php $allCats = GetAllCategories();}
{loop $allCats $topCat}
<div class="category-block">
<h2><a href="{$topCat['typedir']}">{$topCat['typename']}</a></h2>
{if !empty($topCat['children'])}
<ul class="sub-category-list">
{loop $topCat['children'] $sonCat}
<li><a href="{$sonCat['typedir']}">{$sonCat['typename']}</a></li>
{/loop}
</ul>
{/if}
</div>
{/loop}
总结与建议
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
{dede:channel} |
简单、高效、官方推荐 | 需要嵌套来实现父子结构 | 绝大多数分类调用场景,尤其是导航栏。 |
{dede:channelartlist} |
结构清晰、专为导航设计 | 灵活性相对嵌套channel稍差 |
制作网站主导航、带有下拉菜单的分类列表。 |
| SQL查询 | 灵活性最高,可任意筛选排序 | 代码复杂,容易出错,可读性差 | 需要对数据进行特殊处理,或标签无法满足时。 |
| 自定义函数 | 逻辑清晰,可复用,功能强大 | 需要修改PHP文件,对新手不友好 | 复杂的分类列表,或需要在多个地方调用相同逻辑时。 |
给你的建议:
- 如果你是新手或需求是标准的导航菜单,直接使用 方法一 中的
{dede:channelartlist},这是最简单、最正确的选择。 - 如果你只需要一个简单的顶级分类列表,使用
{dede:channel type='top'}。 - 除非你明确知道自己在做什么,否则尽量避免使用方法二(SQL查询),它会让你的模板难以维护。
- 方法三(自定义函数) 是高级用法,当你项目变得复杂时,它会是很好的工具。
