要获得“实际”可见的文章数量,我们需要通过几种方法来过滤掉这些“无效”的内容。

核心问题分析
arclist 的底层查询是基于 dede_archives (文章主表) 和 dede_arctype (栏目表) 的,默认情况下,它不会检查文章的状态字段。
dede_archives 表中控制文章状态的关键字段是:
arcrank:文章权限等级。0:正常可见(默认值)。-1:仅投稿作者可见。-2:从回收站恢复的文章(在后台列表里是灰色的)。-8:审核未通过。
ismake:是否通过审核。0:已通过审核。1:未审核(此字段在新版本中可能已由arcrank替代或合并,但了解它有助于理解旧系统)。
要获得“实际”数量,我们的核心思路就是:只统计 arcrank 字段为 0 的文章。
解决方案
这里提供三种从易到难、从简单到灵活的解决方案,你可以根据自己的需求选择。

使用 channelartlist 标签(推荐,最简单)
如果你的需求是获取每个栏目的实际文章数量,并且不需要在列表页显示文章,channelartlist 是最简单、最高效的解决方案。
channelartlist 标签在调用栏目时,本身就只会统计“可见”的、正常的文章数量,它天然地过滤掉了 arcrank != 0 的文章。
示例:获取指定栏目的实际文章数量
{dede:channelartlist typeid='1,2,3'}
<li>
<a href="[field:typelink/]">[field:typename/]</a>
(实际文章数: <strong>[field:total/]</strong>)
</li>
{/dede:channelartlist}
说明:

typeid='1,2,3':指定要获取数量的栏目ID。[field:total/]:这个标签直接输出该栏目的“实际”文章数量,无需任何额外设置。
优点:
- 极其简单,一行代码搞定。
- 性能最好,因为它在数据库层面就完成了有效文章的统计。
缺点:
- 功能单一,只能获取栏目总数,不能获取文章列表。
修改 arclist 标签的底层查询(推荐,最灵活)
如果你需要在文章列表页(article_list.htm)同时显示文章列表和该栏目的实际文章数量,那么直接修改 arclist 的底层代码是最好的方法。
操作步骤:
-
找到核心文件: 打开
include/taglib/arclist.lib.php文件,这是arclist标签的解析核心。 -
修改查询语句: 在该文件中找到获取总数的SQL查询语句,通常在
GetArcList函数内,找到类似$this->dsql->SetQuery("SELECT ...");的地方。你需要修改
COUNT(*)的查询部分,为其添加arcrank = 0的条件。修改前(大约在第250-270行,具体行数可能因版本而异):
// 获取总数 if ($this->TotalResult == -1) { $this->dsql->SetQuery("SELECT COUNT(*) AS dd FROM `dede_archives` arc WHERE {$this->addSql}"); $this->dsql->Execute('dd'); $row = $this->dsql->GetArray('dd'); $this->TotalResult = $row['dd']; }修改后:
// 获取总数(仅统计正常可见的文章) if ($this->TotalResult == -1) { // 在原有的 addSql 基础上,增加 arcrank = 0 的条件 // 注意:addSql 中已经包含了 arcrank 相关的条件,需要小心处理,避免冲突 // 通常情况下,直接在WHERE子句后追加是安全的 $this->dsql->SetQuery("SELECT COUNT(*) AS dd FROM `dede_archives` arc WHERE {$this->addSql} AND arc.arcrank = 0"); $this->dsql->Execute('dd'); $row = $this->dsql->GetArray('dd'); $this->TotalResult = $row['dd']; } -
保存文件: 保存
arclist.lib.php文件。
效果:
完成上述修改后,你在模板中使用 {dede:arclist ...},它返回的 [field:total/] 值就只会是 arcrank = 0 的文章数量了。
优点:
- 一劳永逸,全局生效。
- 非常灵活,不影响
arclist的其他功能。
缺点:
- 需要修改核心文件,升级 DedeCMS 时可能需要重复修改。
- 需要一定的代码修改能力。
使用自定义SQL查询(最通用)
如果你不想修改核心文件,或者需要在特定的地方获取数量,那么直接使用自定义SQL是最直接的方法。
示例1:在模板中直接获取指定栏目的实际文章数
{dede:sql sql="SELECT COUNT(*) AS total FROM `dede_archives` WHERE typeid = ~typeid~ AND arcrank = 0"}
本栏目共有文章:<strong>[field:total/]</strong> 篇。
{/dede:sql}
说明:
typeid = ~typeid~:这里的~typeid~是一个占位符,DedeCMS 会自动将其替换为当前页面的栏目ID,这是一个非常方便的用法。arcrank = 0:这是过滤条件,确保只计算正常文章。
示例2:在PHP代码中获取
如果你在PHP文件(如 index.php 或自定义页面)中需要获取数量,可以直接执行数据库查询。
require_once (dirname(__FILE__) . "/include/common.inc.php");
$typeid = 1; // 假设我们要获取ID为1的栏目数量
$dsql = new DedeSql(false);
$dsql->SetQuery("SELECT COUNT(*) AS total FROM `dede_archives` WHERE typeid = {$typeid} AND arcrank = 0");
$dsql->Execute('total');
$row = $dsql->GetArray('total');
$actual_count = $row['total'];
echo "栏目ID为 {$typeid} 的实际文章数量是:{$actual_count}";
优点:
- 不修改核心文件,升级无忧。
- 用途广泛,可以在任何地方使用。
缺点:
- 需要手动编写SQL语句,比方案二稍显繁琐。
总结与推荐
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
channelartlist |
仅需获取栏目的实际文章总数。 | 最简单、性能最好。 | 功能单一,不能获取文章列表。 |
修改 arclist.lib.php |
在文章列表页,需要同时显示列表和该栏目的实际总数。 | 最灵活、一劳永逸,与模板完美结合。 | 需修改核心文件,升级可能覆盖。 |
| 自定义SQL | 不想修改核心文件,或在特定位置(如首页、封面页)获取数量。 | 通用、安全,不破坏系统文件。 | 需要手动编写SQL,不够“自动化”。 |
我的建议是:
- 如果只是想显示每个栏目有多少篇文章,首选方案一。
- 如果你的网站是标准的列表页,并且希望
[field:total/]就代表真实数量,强烈推荐方案二,这是最规范和长久的做法。 - 如果只是临时用一次,或者不想动核心文件,用方案三完全没问题。
