- 使用织梦自带的标签:最简单、最推荐的方法,利用
channelartlist标签的totalitem属性。 - 使用自定义SQL:更灵活,可以应对更复杂的需求,比如只显示某个特定栏目下的文章数。
使用 channelartlist 标签(推荐)
这是织梦官方提供的最标准、最简单的方法,它可以直接在顶级栏目循环中获取该栏目及其所有子栏目的文章总数。

(图片来源网络,侵删)
标签代码
{dede:channelartlist typeid='0' typeid2='0'}
<li>
<a href="{dede:field name='typeurl'/}">{dede:field name='typename'/} (<span>{dede:field name='totalitem'/}</span>)</a>
<!-- 如果需要显示子栏目,可以在这里添加 {dede:channel} 循环 -->
</li>
{/dede:channelartlist}
代码详解
{dede:channelartlist ...}: 这是一个用于获取顶级栏目列表的循环标签。typeid='0': 表示获取所有顶级栏目,如果你只想显示指定的几个顶级栏目,可以在这里填写栏目的ID,用英文逗号隔开,typeid='1,3,5'。typeid2='0': 表示不限制二级栏目,通常保持为0即可。
{dede:field name='typeurl'/}: 获取当前栏目的链接地址。{dede:field name='typename'/}: 获取当前栏目的名称。{dede:field name='totalitem'/}: 这是核心! 它会自动计算并显示当前顶级栏目及其所有子栏目下的文章总数。
示例:完整的导航栏代码
下面是一个完整的导航栏HTML结构,包含了子栏目的展示。
<ul id="nav">
{dede:channelartlist typeid='0' typeid2='0'}
<li>
<a href="{dede:field name='typeurl'/}">{dede:field name='typename'/} (<span>{dede:field name='totalitem'/}</span>)</a>
<!-- 子栏目列表 -->
<ul class="subnav">
{dede:channel type='son' noself='yes'}
<li><a href="[field:typeurl/]">[field:typename/] (<span>[field:total/]</span>)</a></li>
{/dede:channel}
</ul>
</li>
{/dede:channelartlist}
</ul>
说明:
- 在子栏目循环
{dede:channel type='son' noself='yes'}中,我们使用了[field:total/]来获取单个子栏目自己的文章数,注意,这里用的是total而不是totalitem,因为totalitem是在channelartlist循环中专用的。
使用自定义SQL(更灵活)
当 channelartlist 的 totalitem 无法满足你的需求时(你只想计算某个特定分类下的文章,或者文章有特定的属性),你可以使用自定义SQL查询。
标签代码
{dede:sql sql='SELECT id,typename,typedir,isdefault,defaultname,issystem,channeltype,corank,moresite,siteurl,sitepath,description FROM dede_arctype WHERE reid = 0 ORDER BY sortrank'}
<li>
<a href="[field:typedir function='str_replace("{cmspath}", "", "@me")'/]">[field:typename/] (<span>
{dede:sql sql='SELECT COUNT(*) as num FROM dede_archives WHERE typeid = [field:id]'}
[field:num/]
{/dede:sql}
</span>)</a>
</li>
{/dede:sql}
代码详解
-
外层循环
dede:sql:
(图片来源网络,侵删)sql='SELECT ... FROM dede_arctype WHERE reid = 0 ORDER BY sortrank': 这个SQL查询dede_arctype(栏目表)中所有顶级栏目(reid = 0表示父ID为0,即顶级栏目)。[field:id/]: 获取当前栏目的ID。[field:typename/]: 获取当前栏目的名称。[field:typedir/]: 获取当前栏目的目标目录路径。
-
内层循环
dede:sql:sql='SELECT COUNT(*) as num FROM dede_archives WHERE typeid = [field:id]': 这是核心查询。SELECT COUNT(*) as num: 计算文章数量,并将结果命名为num。FROM dede_archives: 从文章主表dede_archives中查询。WHERE typeid = [field:id]: 条件是文章的typeid等于当前外层循环栏目的ID。
[field:num/]: 输出查询到的文章数量。
注意事项
- 性能问题:这种方法对于每个顶级栏目,都会再执行一次SQL查询来计算文章数,如果你的网站栏目非常多,可能会对数据库造成一定的压力,对于大多数普通网站来说,影响不大,但对于大型网站,建议使用缓存或更优化的查询。
- 文章状态:默认情况下,
dede_archives表会包含所有状态(正常、待审核、回收站等)的文章,如果你只想计算“已审核”的文章,需要修改SQL,增加WHERE arcrank = -1条件:{dede:sql sql='SELECT COUNT(*) as num FROM dede_archives WHERE typeid = [field:id] AND arcrank = -1'} [field:num/] {/dede:sql}
总结与对比
| 特性 | 方法一 (channelartlist) |
方法二 (自定义SQL) |
|---|---|---|
| 易用性 | 非常高,官方标签,代码简洁。 | 较低,需要了解SQL语法。 |
| 性能 | 较好,织梦内部进行了优化。 | 一般,每个栏目都会增加一次查询。 |
| 灵活性 | 较低,主要满足常规需求。 | 非常高,可以添加各种复杂条件。 |
| 适用场景 | 绝大多数情况下的首选,快速实现导航栏文章数统计。 | 特殊需求,如只统计某个模型的文章、只统计已审核文章等。 |
建议:首先尝试方法一,它能解决90%以上的问题,只有在遇到方法一无法满足的特殊业务逻辑时,再考虑使用方法二。
