dede listsql如何实现动态传参?

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

listsqlarclistlist 标签的一个强大功能,它允许你直接手写 SQL 查询语句,从而实现比常规调用标签更灵活、更复杂的列表数据获取,动态传参则是让这个功能变得实用的关键。

dede listsql 动态传参
(图片来源网络,侵删)

核心原理

动态传参的核心是利用 DedeCMS 的模板引擎机制,它会解析模板中的特定标签(如 {dede:field}),将 PHP 代码中定义的变量值替换掉模板中的占位符,然后再执行最终的 SQL 查询。


场景示例

假设我们要做一个文章列表页,可以根据 URL 传递过来的 typeid (栏目ID) 和 keyword (关键词) 来动态筛选文章。

目标URL示例:

  • http://yourdomain.com/list.php?tid=5&k=织梦 (获取栏目ID为5,标题包含“织梦”的文章)
  • http://yourdomain.com/list.php?tid=8 (仅获取栏目ID为8的文章)

实现步骤

第 1 步:修改模板文件 (list_article.htm)

在你的列表模板文件中,找到调用文章列表的 arclistlist 标签,将它的 sql 属性(注意是 sql,不是 listsqllistsqllist 标签的属性,arclist 标签用的是 sql)设置为一个包含 PHP 变量的 SQL 模板。

dede listsql 动态传参
(图片来源网络,侵删)
{dede:list sql="SELECT arc.*,tp.typedir,tp.typename,tp.corank,tp.isdefault,tp.defaultname,tp.moresite,tp.siteurl,tp.sitepath 
                 FROM `dede_archives` arc 
                 LEFT JOIN `dede_arctype` tp ON arc.typeid=tp.id 
                 WHERE 1=1 
                 AND arc.arcrank > -1 
                 [field:typeid function="GetSonIds(@me)"/] 
                 AND arc.title LIKE '%[field:keyword]%' 
                 ORDER BY arc.sortrank DESC LIMIT 0,10"}
    <li>
        <a href="[field:arcurl/]">[field:title/]</a>
        <span>[field:pubdate function="MyDate('Y-m-d',@me)"/]</span>
    </li>
{/dede:list}

模板代码解析:

  1. sql="...": 我们在这里直接写 SQL 查询语句。
  2. WHERE 1=1: 这是一个常用的 SQL 技巧,方便后续添加 AND 条件,而不用担心第一个条件是 AND 还是 WHERE
  3. [field:typeid function="GetSonIds(@me)"/]: 这是动态传参的关键部分。
    • [field:typeid]: 这是一个模板标签,它会尝试获取一个名为 typeid 的变量。
    • function="GetSonIds(@me)": 这是 DedeCMS 的一个内置函数,如果传入了 typeid,它会获取该栏目及其所有子栏目的 ID,并用 连接起来,5,12,13typeid 为空,这个函数会返回空字符串,这样 SQL 语句就变成了 WHERE 1=1 AND (),这会报错,所以我们需要在 PHP 代码中处理这种情况。
  4. AND arc.title LIKE '%[field:keyword]%': 同样,[field:keyword] 会获取 URL 中传递的 k 参数的值。

注意: list 标签默认不支持调用栏目信息(如 tp.typename),所以这里我们直接使用 arclist 标签的 sql 属性会更方便,如果你的模板是 list 标签,并且需要复杂查询,建议直接替换为 arclist

第 2 步:修改 PHP 文件 (list.php)

这是实现动态传参的核心,我们需要修改 list.php 文件,在它执行模板渲染之前,获取 URL 参数并设置给模板引擎。

打开 /plus/list.php 文件,找到类似下面的代码:

// ...
require_once(dirname(__FILE__)."/../include/common.inc.php");
require_once(DEDEINC."/arc.listview.class.php");
$tid = isset($tid) && is_numeric($tid) ? $tid : 0;
// ... 获取分页等其他参数 ...
$lv = new ListView($tid,$typeid,$channelid,$totalresult,$keyword,$tagid,$pageno);
$lv->SetTemplate($tempfile);
$lv->SaveToHtml();
$lv->Display();
// ...

我们需要在 new ListView(...) 之前,处理我们的参数。

修改后的 list.php 关键代码:

<?php
require_once(dirname(__FILE__)."/../include/common.inc.php");
require_once(DEDEINC."/arc.listview.class.php");
// --- 开始修改 ---
// 1. 获取并处理 typeid 参数
$dynamic_typeid = isset($tid) && is_numeric($tid) ? intval($tid) : 0;
// 2. 获取并处理 keyword 参数
$dynamic_keyword = isset($k) ? trim($k) : '';
// 3. 将参数传递给模板,覆盖默认的 $tid 和 $keyword
//    这里的 'typeid' 和 'keyword' 必须和模板中的 [field:typeid] 和 [field:keyword] 对应
$GLOBALS['typeid'] = $dynamic_typeid;
$GLOBALS['keyword'] = $dynamic_keyword;
// --- 修改结束 ---
// ... 后面的代码保持不变,但要注意 $typeid 变量已经被我们覆盖了 ...
// 如果后续代码还需要原始的 $typeid,请使用另一个变量名保存
$tid = isset($tid) && is_numeric($tid) ? $tid : 0; // 这里的 $tid 已经是我们动态设置的值了
$typeid = $tid; // arc.listview.class.php 内部使用 $typeid,可以这样同步
// ... 获取分页等其他参数 ...
$lv = new ListView($tid,$typeid,$channelid,$totalresult,$keyword,$tagid,$pageno);
$lv->SetTemplate($tempfile);
$lv->SaveToHtml();
$lv->Display();

PHP 代码解析:

  1. $dynamic_typeid = isset($tid) ? ...: 从 URL 中获取 tid 参数,并进行安全处理(intval)。
  2. $dynamic_keyword = isset($k) ? ...: 从 URL 中获取 k 参数(kkeyword 的简写,更美观)。
  3. $GLOBALS['typeid'] = $dynamic_typeid;: 这是最关键的一步! 我们将获取到的值赋值给一个全局变量 $GLOBALS,DedeCMS 的模板引擎会自动查找 $GLOBALS 数组中的变量,并将其暴露给模板使用,模板中的 [field:typeid] 实际上就是从这里取值的。
  4. $GLOBALS['keyword'] = $dynamic_keyword;: 同理,将关键词也传递给模板。

第 3 步:优化模板 SQL 语句(防止 SQL 错误)

回到模板,我们发现如果 typeidkeyword 为空,SQL 语句可能会出错,我们可以用 DedeCMS 的 if 标签来优化。

{dede:list sql="SELECT arc.*,tp.typedir,tp.typename,tp.corank,tp.isdefault,tp.defaultname,tp.moresite,tp.siteurl,tp.sitepath 
                 FROM `dede_archives` arc 
                 LEFT JOIN `dede_arctype` tp ON arc.typeid=tp.id 
                 WHERE 1=1 
                 AND arc.arcrank > -1 
                 [field:typeid runphp='yes']
                     if(@me != '') @me = " AND arc.typeid IN (".@me.")";
                     else @me = "";
                 [/field:typeid]
                 [field:keyword runphp='yes']
                     if(@me != '') @me = " AND arc.title LIKE '%".@me."%'";
                     else @me = "";
                 [/field:keyword]
                 ORDER BY arc.sortrank DESC LIMIT 0,10"}
    <!-- ... 循环体 ... -->
{/dede:list}

优化后的模板代码解析:

  1. [field:typeid runphp='yes']...[/field:typeid]: 对 typeid 参数进行 PHP 处理。
    • runphp='yes': 启用 PHP 解析。
    • if(@me != ''): 判断获取到的值是否为空。
    • @me = " AND arc.typeid IN (".@me.")";: 如果不为空,则拼接成有效的 SQL 条件,注意这里用 IN 而不是 ,因为 GetSonIds 函数返回的是多个 ID。
    • else @me = "";: 如果为空,则设置为空字符串,避免 SQL 语法错误。
  2. [field:keyword runphp='yes']...[/field:keyword]: 同理,对 keyword 参数进行 PHP 处理,只有在有值的时候才拼接 LIKE 查询。

总结与最佳实践

  1. 模板与 PHP 分离: 模板只负责展示逻辑,PHP 负责数据准备和传递,这是现代开发的基本原则。
  2. 安全性: 永远不要直接信任用户输入,像示例中那样,对 intval($tid)trim($k) 进行处理,可以有效防止 SQL 注入和 XSS 攻击。
  3. SQL 复杂度: listsql (或 sql) 虽然强大,但写复杂的 SQL 语句容易出错,且不利于后续维护,如果查询逻辑非常复杂,可以考虑在 PHP 中先查询好数据,再通过 array 标签传递给模板。
  4. 变量命名: 为了清晰,建议在 PHP 中使用不同的变量名(如 $dynamic_typeid)来接收参数,然后统一赋值给 $GLOBALS 供模板使用,避免混淆。
  5. 性能: 直接写 SQL 通常比 DedeCMS 内置的标签解析效率更高,因为它减少了标签解析的开销,但对于简单列表,推荐使用标准的 arclistlist 标签,代码更简洁,也方便后台缓存。

通过以上步骤,你就可以在 DedeCMS 中灵活地使用 listsql 并实现各种动态传参的需求了。

-- 展开阅读全文 --
头像
struct player如何定义与使用?
« 上一篇 2025-12-16
Ubuntu 14.04下C语言如何入门?
下一篇 » 2025-12-16

相关文章

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

目录[+]