dede limit为何不包括当前条目?

99ANYc3cd6
预计阅读时长 17 分钟
位置: 首页 DEDE建站 正文

DedeCMS 的 limit 参数本身并没有“包括”或“不包括”当前记录的选项,它的作用是“从结果集中的第 N 条开始,取 M 条记录”。

这里的“当前记录”通常有两种理解:

  1. 当前正在被循环的单条记录limit 的作用域是整个查询结果集,而不是单条记录。limit 天然就不“包括”正在循环的这条记录本身,因为它的作用是在循环开始前就截取了数据。
  2. 当前页面的那条记录:这是最常见的需求,即在一个列表页(如文章列表、产品列表)中,希望排在第一位的文章(也就是当前文章)不显示在推荐、相关文章等列表里。

下面我们针对这两种情况,特别是第二种常见情况,提供详细的解决方案。


排除当前正在循环的单条记录(不常用,但需理解)

这种情况基本不需要特殊处理,因为 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。

核心思路

  1. 获取当前文章的ID:[field:id/
  2. 获取当前栏目的所有文章ID:使用 {dede:sql} 查询。
  3. 将所有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 来实现。

核心思路

  1. 先查询出当前文章的ID。
  2. arclist 中使用 orderby='rand' 随机排序。
  3. 使用 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代码。

核心思路

  1. 在模板文件中嵌入PHP代码。
  2. 使用PHP获取当前文章ID和栏目ID。
  3. 构建一个排除当前ID的SQL查询。
  4. 使用 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 灵活性最高 代码复杂,需要编程基础

对于绝大多数“排除当前文章”的需求,强烈推荐使用方法一,它既简单又高效。

-- 展开阅读全文 --
头像
织梦网站后台如何操作?
« 上一篇 01-05
树上的织梦网如何拿下来
下一篇 » 01-05

相关文章

取消
微信二维码
支付宝二维码

目录[+]