在 DedeCMS (织梦CMS) 中,判断一个栏目是否有子栏目(即二级菜单),通常是在模板文件(.htm)中通过调用系统提供的标签或 PHP 代码来实现的,以下是几种常用且有效的方法:

使用 {dede:channel} 标签的 typeid 和 reid 属性
这是最常用和推荐的方法,尤其适用于栏目导航的循环输出。
场景:在一级栏目循环中,判断当前栏目是否有子栏目。
模板代码示例:
{dede:channel type='top' typeid='0' currentstyle='
<li class="active"><a href='~typelink~'>~typename~</a></li>
'}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
<!-- 开始判断是否有子栏目 -->
{dede:field name='typeid' runphp='yes'}
$dsql = new DedeSql(false);
$row = $dsql->GetOne("SELECT COUNT(*) AS num FROM `dede_arctype` WHERE reid='@me'");
if ($row['num'] > 0) {
// 有子栏目,输出二级菜单
echo '<ul class="sub-menu">';
// 循环输出子栏目
@me = "
{dede:channel type='son' typeid='@me'}
<li><a href='[field:typelink/]'>[field:typename/]</a></li>
{/dede:channel}
";
echo '</ul>';
} else {
// 没有子栏目,输出空内容
@me = '';
}
{/dede:field}
</li>
{/dede:channel}
代码解析:

{dede:channel type='top' ...}:首先获取所有顶级栏目。{dede:field name='typeid' runphp='yes'}:对每个顶级栏目,获取其typeid,并通过runphp='yes'执行 PHP 代码。$dsql->GetOne(...):在 PHP 代码块中,执行 SQL 查询,统计dede_arctype(栏目表) 中reid(父栏目ID) 等于当前栏目typeid的记录数。if ($row['num'] > 0):如果查询结果大于0,说明存在子栏目。{dede:channel type='son' typeid='@me'}:如果存在子栏目,则使用type='son'来获取当前栏目的所有直接子栏目,typeid='@me'将 PHP 变量@me(即当前栏目的typeid)传递给子栏目查询。@me = '...':将拼接好的 HTML 字符串赋值给@me变量,这部分内容会替换掉整个{dede:field...}else { @me = ''; }:如果没有子栏目,则输出空字符串。
使用 {dede:arclist} 标签(适用于内容页)
如果你在文章内容页( 模板代码示例: 代码解析: 这种方法与方法一的核心逻辑相同,只是触发场景不同,它是在文章页获取当前文章的栏目ID,然后去查询该栏目是否有下级栏目。 如果你的模板中多处需要此功能,或者希望模板代码更清晰,推荐使用自定义函数。 步骤 1:创建自定义函数文件 在 步骤 2:在模板中调用函数 你的模板代码会变得非常简洁。 模板代码示例(顶级栏目循环): 代码解析: 对于大多数项目,方法三(自定义函数) 是最理想的选择。article_article.htm)中,想判断当前文章所属的栏目是否有子栏目,可以使用 arclist
{dede:field name='typeid' runphp='yes'}
$hasChildren = false;
$dsql = new DedeSql(false);
$dsql->SetQuery("SELECT id FROM `dede_arctype` WHERE reid='@me' LIMIT 1");
$dsql->Execute();
if ($dsql->GetRow()) {
$hasChildren = true;
}
if ($hasChildren) {
echo "当前栏目有二级菜单!";
// 这里可以调用子栏目列表
echo "<ul>";
@me = "
{dede:channel type='son' typeid='@me'}
<li><a href='[field:typelink/]'>[field:typename/]</a></li>
{dede:channel}
";
echo "</ul>";
} else {
echo "当前栏目没有二级菜单。";
@me = '';
}
{/dede:field}
使用自定义函数(更推荐,代码更整洁)

/include/extend.func.php 文件中(如果不存在则创建)添加以下 PHP 函数:/**
* 判断指定栏目ID是否有子栏目
* @param int $typeid 栏目ID
* @return bool 有子栏目返回true,否则返回false
*/
function HasSonChannel($typeid) {
if (empty($typeid)) {
return false;
}
$dsql = new DedeSql(false);
$row = $dsql->GetOne("SELECT COUNT(*) AS num FROM `dede_arctype` WHERE reid='$typeid'");
$dsql->Close();
return ($row['num'] > 0);
}
{dede:channel type='top' typeid='0'}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
<!-- 调用自定义函数判断 -->
{if HasSonChannel([field:typeid/])}
<!-- 有子栏目,输出二级菜单 -->
<ul class="sub-menu">
{dede:channel type='son' typeid='[field:typeid/]'}
<li><a href='[field:typelink/]'>[field:typename/]</a></li>
{/dede:channel}
</ul>
{/if}
</li>
{/dede:channel}
HasSonChannel([field:typeid/]):直接调用我们在 extend.func.php 中定义的函数,并将当前栏目的 typeid 作为参数传入。{if ...}:根据函数返回的 true 或 false 来决定是否输出子菜单的 HTML 结构。
方法
优点
缺点
适用场景
{dede:field} + runphp无需额外文件,直接在模板中实现
模板中嵌入PHP代码,可读性稍差,不易复用
简单的、一次性的判断需求
{dede:arclist} + runphp页判断
同方法一,且与内容列表标签混合,逻辑不够清晰
在文章页判断其栏目是否有下级
自定义函数
代码最整洁,逻辑与视图分离,易于复用和维护
需要额外修改PHP文件
强烈推荐,尤其适用于项目中有多个地方需要此功能时
