最核心、最常用的方法是使用 TypeLink 标签结合 hasChildren 变量。

(图片来源网络,侵删)
最常用、最推荐的方法(TypeLink + hasChildren)
这是织梦官方推荐且最简洁的方法。TypeLink 标签会自动解析出栏目的层级关系,并通过 hasChildren 这个布尔值(真/假)来判断。
适用场景
- 在导航栏循环中,判断当前栏目是否需要显示下拉菜单。
- 在栏目列表页,判断当前栏目下是否还有子栏目。
标签代码示例
假设你要在主导航栏中循环输出所有顶级栏目,并为有子栏目的栏目添加一个下拉箭头或下拉菜单。
{dede:channelartlist typeid='0' row='10'}
<li>
<a href="{dede:field name='typeurl'/}">{dede:field name='typename'/}</a>
<!-- 关键判断:hasChildren 为真,则显示子栏目列表 -->
[field:hasChildren runphp='yes']
if(@me) {
@me = '<ul class="sub-nav">';
@me .= dede_get_son(@me);
@me .= '</ul>';
} else {
@me = '';
}
[/field:hasChildren]
</li>
{/dede:channelartlist}
代码解析:
-
{dede:channelartlist typeid='0' row='10'}:
(图片来源网络,侵删)typeid='0': 表示获取所有顶级栏目。row='10': 限制只显示10个顶级栏目。- 这个标签会循环每一个顶级栏目。
-
{dede:field name='typeurl'/}和{dede:field name='typename'/}:分别输出当前顶级栏目的链接和名称。
-
[field:hasChildren runphp='yes']:- 这是核心部分。
hasChildren是channelartlist标签自动生成的变量,表示当前栏目是否有子栏目。 runphp='yes'允许我们在PHP代码块中处理这个变量。
- 这是核心部分。
-
if(@me):@me在runphp中代表当前标签的值。hasChildren的值是1(有子栏目) 或0(无子栏目)。if(@me)等同于if(1)或if(0),可以用来判断条件是否成立。
-
@me = dede_get_son(@me);:- 这是一个织梦内置函数,用于获取当前栏目的所有子栏目,它会返回一个包含所有子栏目链接和列表的HTML字符串。
- 注意:这里的
@me在函数调用前是hasChildren的值,调用后@me会被函数的返回值(即子栏目的HTML)覆盖。
-
简化写法(更常用): 你不需要写这么复杂的PHP判断,织梦的
sonclass变量可以直接使用。{dede:channelartlist typeid='0' row='10'} <li> <a href="{dede:field name='typeurl'/}">{dede:field name='typename'/}</a> <!-- 直接使用 sonclass 变量,它会自动判断并生成子栏目列表 --> {dede:field name='sonclass'/} </li> {dede:channelartlist}sonclass变量在后台的“栏目调用”标签设置中,默认就是“只显示栏目链接”,它会自动处理hasChildren的判断,hasChildren为真,它才会输出子栏目的列表。
使用SQL查询(灵活但稍复杂)
如果你想在更复杂逻辑中判断,或者不使用 channelartlist 标签,可以直接执行SQL查询。
适用场景
- 在自定义PHP文件或模型中判断。
- 需要结合其他复杂条件进行判断。
思路
查询 dede_arctype 表,找到当前栏目的ID,然后检查 reid (父栏目ID) 字段等于当前栏目ID的记录是否存在。
示例代码(在模板中使用 runphp)
假设你当前在某个栏目的内容页,想判断这个栏目是否有子栏目。
{dede:field name='typeid' runphp='yes'}
$typeid = @me; // 获取当前栏目的ID
// 引入数据库配置
require_once(DEDEROOT.'/data/common.inc.php');
// 执行SQL查询
$dsql->SetQuery("SELECT COUNT(*) as num FROM `#@__arctype` WHERE `reid` = $typeid");
$dsql->Execute();
$row = $dsql->GetObject();
// 如果查询结果大于0,则有子栏目
if ($row->num > 0) {
@me = '本栏目有子栏目!';
} else {
@me = '本栏目没有子栏目。';
}
{/dede:field}
代码解析:
{dede:field name='typeid' runphp='yes'}: 获取当前内容或栏目页的ID,并启用PHP。$typeid = @me;: 将获取到的ID保存到变量$typeid中。require_once(DEDEROOT.'/data/common.inc.php');: 引入织梦的数据库配置文件,以便使用$dsql数据库对象。$dsql->SetQuery(...): 设置SQL查询语句。#@__arctype: 这是织梦的表名前缀机制,#@__会被替换为你在配置中设置的表前缀(如dede_)。reid是dede_arctype表中记录父栏目ID的字段。COUNT(*) as num: 计算子栏目的数量。
$dsql->Execute();: 执行查询。$row = $dsql->GetObject();: 获取查询结果。if ($row->num > 0): 判断查询到的数量是否大于0。@me = '...';: 根据判断结果,给@me赋值,这个值会最终显示在页面上。
总结与建议
| 方法 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
TypeLink / sonclass |
代码简洁,效率高,官方推荐 | 灵活性相对较低,主要用于模板循环 | 导航栏、栏目列表页等绝大多数场景 |
| SQL查询 | 灵活性极高,可结合任何复杂条件 | 代码量大,需要手动处理数据库连接,效率稍低 | 在自定义PHP文件、复杂模型或需要特殊逻辑时使用 |
对于99%的模板开发需求,强烈推荐使用方法一,它既简单又高效,是织梦CMS的内置特性,专门为此类场景设计,只有在方法一无法满足需求时,才考虑使用方法二。
