DedeCMS 的 limit 参数本身并没有“包括”或“不包括”当前记录的选项,它的作用是“从结果集中的第 N 条开始,取 M 条记录”。
这里的“当前记录”通常有两种理解:
- 当前正在被循环的单条记录:
limit的作用域是整个查询结果集,而不是单条记录。limit天然就不“包括”正在循环的这条记录本身,因为它的作用是在循环开始前就截取了数据。 - 当前页面的那条记录:这是最常见的需求,即在一个列表页(如文章列表、产品列表)中,希望排在第一位的文章(也就是当前文章)不显示在推荐、相关文章等列表里。
下面我们针对这两种情况,特别是第二种常见情况,提供详细的解决方案。
排除当前正在循环的单条记录(不常用,但需理解)
这种情况基本不需要特殊处理,因为 limit 的作用是在循环前就决定了要取哪些数据。
假设你有一个循环,想在每条记录后面都附加一个“下一篇”的链接,这个“下一篇”自然就是当前记录的下一条。
错误的理解:有人可能会想用 limit='1,1' 来“取下一条一条记录”,但这会从整个结果集的第二条开始取,而不是当前记录的下一条。
正确的做法:DedeCMS 为此专门提供了标签 [field:nexturl/],它会自动获取当前记录的下一篇链接,无需手动使用 limit。
示例代码:
{dede:arclist typeid='1' titlelen='30'}
<li>
<a href="[field:arcurl/]">[field:title/]</a>
<!-- 下一篇文章链接,[field:nexturl/] 会自动处理 -->
<a href="[field:nexturl/]">下一篇</a>
</li>
{/dede:arclist}
在这个例子里,limit 完全用不上,因为 [field:nexturl/] 已经实现了“不包括当前,取下一条”的逻辑。
排除当前页面的那条记录(最常见的需求)
这是指,你在文章详情页 (article_article.htm),想调用该栏目下的其他文章列表,但不希望显示当前正在浏览的这篇文章。
使用 idlist + not 参数(推荐,最简单)
这是最直接、最优雅的方法。idlist 用于指定要显示的文章ID列表,而 not 参数可以从这个列表中排除某些ID。
核心思路:
- 获取当前文章的ID:
[field:id/ - 获取当前栏目的所有文章ID:使用
{dede:sql}查询。 - 将所有ID组合成一个列表,然后用
not排除当前ID。
示例代码(在文章详情页 article_article.htm 中):
<h3>相关文章</h3>
<ul>
<!--
1. {dede:sql} 查询当前栏目 (typeid=[field:typeid/]) 的所有文章ID
2. idlist='@me' 将查询到的ID列表作为参数传入 arclist
3. not='@me' 从这个ID列表中排除当前文章的ID ([field:id/])
4. row='10' 限制显示10条
5. titlelen='30' 标题长度30
-->
{dede:arclist idlist='(SELECT id FROM dede_archives WHERE typeid=[field:typeid/])' not='[field:id/]' row='10' titlelen='30'}
<li><a href="[field:arcurl/]">[field:title/]</a></li>
{/dede:arclist}
</ul>
代码解释:
typeid=[field:typeid/]:获取当前文章所属的栏目ID。idlist='(SELECT id FROM ...)':这是一个子查询,它会找出当前栏目下所有文章的ID,并生成一个逗号分隔的ID字符串(12,15,18,23)。not='[field:id/]':@me在这里代表idlist的值,所以这句的意思是,从idlist列表中排除当前文章的ID。row='10':最终只显示10条符合条件的文章。
优点:
- 代码简洁,逻辑清晰。
- 性能较好,因为数据库直接处理了排除逻辑。
使用 orderby='rand' + limit(随机推荐)
如果你只是想随机推荐几篇文章,并且不希望包含当前文章,可以结合 orderby='rand' 和 limit 来实现。
核心思路:
- 先查询出当前文章的ID。
- 在
arclist中使用orderby='rand'随机排序。 - 使用
limit='1,10'来跳过第一条记录。这并不能保证跳过的一定是当前文章!
这个方法不精确,仅适用于“随机推荐,且大概率不包含当前文章”的场景,不推荐用于需要精确排除的“相关文章”。
示例代码(不推荐用于精确排除):
<h3>随机推荐文章</h3>
<ul>
<!-- 这种方法无法保证排除当前文章,只是随机跳过一条 -->
{dede:arclist typeid='1' orderby='rand' limit='1,10' titlelen='30'}
<li><a href="[field:arcurl/]">[field:title/]</a></li>
{dede:arclist}
</ul>
缺点:
- 不精确:
limit='1,10'只是跳过随机排序后的第一条,它不一定是当前文章。
使用PHP和SQL结合(最灵活,但代码稍复杂)
如果方法一不能满足你的特殊需求(需要根据其他字段排序),你可以在模板文件中直接使用PHP代码。
核心思路:
- 在模板文件中嵌入PHP代码。
- 使用PHP获取当前文章ID和栏目ID。
- 构建一个排除当前ID的SQL查询。
- 使用
GetSql()或dsql执行查询并循环输出。
示例代码(在 article_article.htm 中):
<h3>相关文章(PHP方法)</h3>
<ul>
<?php
// 获取当前文章ID和栏目ID
$arcid = $arcID; // 在文章详情页,$arcID 全局变量已存在
$typeid = $typeid; // 同理,$typeid 也已存在
if ($arcid && $typeid) {
// 构建查询,排除当前文章ID,按发布时间倒序,取10条
$query = "SELECT id, title FROM dede_archives
WHERE typeid = $typeid AND id <> $arcid
ORDER BY pubdate DESC
LIMIT 0, 10";
// 使用 dsql 执行查询
$dsql = new DedeSql(false);
$dsql->SetQuery($query);
$dsql->Execute('list');
while ($row = $dsql->GetArray('list')) {
$title = htmlspecialchars($row['title']);
$url = GetArcUrl($row['id'], $row['typeid'], $row['senddate'], $row['title'], $row['ismake'], $row['arcrank']);
echo "<li><a href='{$url}'>{$title}</a></li>";
}
$dsql->Close();
}
?>
</ul>
优点:
- 极其灵活:可以编写任何复杂的SQL逻辑,如多表联合查询、按任意字段排序等。
- 性能可控:完全由你控制SQL语句。
缺点:
- 代码量较大,不如方法一简洁。
- 需要一定的PHP和SQL基础。
| 需求场景 | 推荐方法 | 优点 | 缺点 |
|---|---|---|---|
| 排除当前文章,调用其他文章 | idlist + not |
代码简洁,性能好,逻辑清晰 | 无明显缺点 |
| 随机推荐,不包含当前文章 | orderby='rand' + limit |
实现简单 | 不精确,无法保证排除当前文章 |
| 需要复杂排序或查询逻辑 | PHP + SQL | 灵活性最高 | 代码复杂,需要编程基础 |
对于绝大多数“排除当前文章”的需求,强烈推荐使用方法一,它既简单又高效。
