dede模板执行php时,sql如何安全高效运行?

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

我会按照从安全到不安全的顺序,为你介绍几种实现方法,并强烈推荐使用安全的方式。

dede模板详情执行php 内sql
(图片来源网络,侵删)

场景假设

假设我们要在文章详情页(article_article.htm)中,获取与当前文章同分类下的其他5篇文章,并显示它们的标题和链接。


使用 {dede:php} 标签(最直接,但需谨慎)

这是最直接的方法,允许你在模板中直接嵌入PHP代码。

修改模板配置文件

你需要确保你的模板配置文件(templets/plus/view_template.phptemplets/default/article_article.php)中启用了 php

打开你的模板PHP文件,找到类似 $cfg_fckphp = 'Y'; 的地方,确保PHP标签被允许,DedeCMS默认是允许的。

在模板文件中编写代码

打开你的详情页模板文件,templets/default/article_article.htm,在你需要显示同分类文章的位置,插入如下代码:

dede模板详情执行php 内sql
(图片来源网络,侵删)
<h3>同分类文章推荐</h3>
<ul>
{dede:php}
    // 1. 获取当前文章的ID和分类ID
    // $aid 和 $typeid 是DedeCMS在详情页默认提供的变量
    $arcId = $aid;
    $typeId = $typeid;
    // 2. 安全地获取SQL查询参数 (防止SQL注入)
    $arcId = intval($arcId);
    $typeId = intval($typeId);
    // 3. 编写SQL查询语句
    // 注意:这里使用了 `arc.id <> $arcId` 来排除当前文章
    $sql = "SELECT id, title FROM `#@__archives` 
            WHERE typeid = {$typeId} AND id <> {$arcId} 
            ORDER BY pubdate DESC 
            LIMIT 5";
    // 4. 执行查询
    $dsql->SetQuery($sql);
    $dsql->Execute('me');
    // 5. 循环输出结果
    while ($row = $dsql->GetArray('me')) {
        $title = $row['title'];
        $url = GetArcUrl($row['id'], $row['typeid']); // 使用DedeCMS内置函数获取链接
        echo "<li><a href='{$url}'>{$title}</a></li>";
    }
{/dede:php}
</ul>

代码解析:

  • {dede:php}...{/dede:php}: 这是DedeCMS的PHP执行标签。
  • $aid, $typeid: DedeCMS在文章详情页模板中自动提供的全局变量,分别代表当前文章的ID和分类ID。
  • intval(): 非常重要! 对所有来自外部或模板变量的数值进行过滤,防止SQL注入攻击。
  • $dsql: DedeCMS的全局数据库连接对象,可以直接使用。
  • SetQuery()Execute(): 执行SQL语句的标准方法。
  • GetArray(): 获取查询结果的一行数据。
  • GetArcUrl(): DedeCMS内置函数,用于根据文章ID和分类ID生成正确的URL,比手动拼接 plus/view.php?aid=xxx 更可靠。

使用 {dede:sql} 标签(更安全,推荐)

这是DedeCMS官方推荐的、在模板中执行SQL查询的方法,它比 {dede:php} 更安全,因为它只允许执行查询,并且对传入的参数有内置的过滤机制。

编写SQL标签代码

同样在 article_article.htm 模板中,你可以这样写:

<h3>同分类文章推荐 (使用sql标签)</h3>
<ul>
{dede:sql sql='
    SELECT id, title 
    FROM `#@__archives` 
    WHERE typeid = ~typeid~ AND id <> ~aid~ 
    ORDER BY pubdate DESC 
    LIMIT 5'
}
    <li>
        <a href='[field:phpurl/]/view.php?aid=[field:id/]'>[field:title/]</a>
    </li>
{/dede:sql}
</ul>

代码解析:

dede模板详情执行php 内sql
(图片来源网络,侵删)
  • {dede:sql}: DedeCMS的SQL执行标签。
  • sql='...': 属性中填入你的SQL语句。
  • ~typeid~~aid~: 这是 变量替换符,DedeCMS会自动将模板中可用的变量(如$typeid, $aid)的值替换到这里。这是最安全的方式,DedeCMS底层会处理好这些变量的转义,防止SQL注入。
  • [field:id/][field:title/]: 这是在 {dede:sql} 标签内获取查询结果字段的方式,类似于 {dede:arclist} 中的用法。
  • [field:phpurl/]: 这是获取网站 plus 目录URL的内置方法,比硬编码 plus/ 更灵活。

为什么推荐 {dede:sql}

  1. 安全性高:变量替换机制 (~var~) 自动防止了SQL注入。
  2. 语法简洁:无需编写PHP循环代码,模板更清晰。
  3. 功能专注:只做数据查询,职责单一。

修改PHP源文件(最规范、最灵活)

对于非常复杂且需要多次复用的逻辑,最佳实践是修改DedeCMS的PHP源文件,然后在模板中调用。

创建自定义函数文件

/include/helpers/ 目录下创建一个新文件,extend.helper.php

extend.helper.php 中编写你的函数:

<?php
if (!defined('DEDEINC')) exit('dedecms');
/**
 * 获取同分类下的推荐文章
 * @param int $aid 当前文章ID
 * @param int $typeid 当前文章分类ID
 * @param int $rowNum 获取数量
 * @return array 文章列表数组
 */
function GetSameCategoryArticles($aid, $typeid, $rowNum = 5)
{
    global $dsql;
    // 安全过滤
    $aid = intval($aid);
    $typeid = intval($typeid);
    $rowNum = intval($rowNum);
    $sql = "SELECT id, title FROM `#@__archives` 
            WHERE typeid = {$typeid} AND id <> {$aid} 
            ORDER BY pubdate DESC 
            LIMIT 0, {$rowNum}";
    $result = $dsql->GetAll($sql);
    return $result;
}

在模板中调用函数

你的模板文件 article_article.htm 变得非常干净:

<h3>同分类文章推荐 (调用自定义函数)</h3>
<ul>
{dede:php}
    // 调用我们刚刚创建的函数
    $sameArticles = GetSameCategoryArticles($aid, $typeid, 5);
    if (!empty($sameArticles)) {
        foreach ($sameArticles as $article) {
            $url = GetArcUrl($article['id'], $article['typeid']);
            echo "<li><a href='{$url}'>{$article['title']}</a></li>";
        }
    }
{/dede:php}
</ul>

或者,如果你想让模板更简洁,可以在PHP文件里把HTML也处理好,然后只输出一个变量。

(可选)在PHP文件中处理HTML并赋值给模板变量

修改 /include/helpers/extend.helper.php

<?php
// ... (前面的函数GetSameCategoryArticles保持不变) ...
/**
 * 获取同分类文章推荐并生成HTML列表
 * @param int $aid 当前文章ID
 * @param int $typeid 当前文章分类ID
 * @param int $rowNum 获取数量
 * @return string HTML列表字符串
 */
function GetSameCategoryHtmlList($aid, $typeid, $rowNum = 5)
{
    global $dsql;
    $aid = intval($aid);
    $typeid = intval($typeid);
    $rowNum = intval($rowNum);
    $sql = "SELECT id, title FROM `#@__archives` 
            WHERE typeid = {$typeid} AND id <> {$aid} 
            ORDER BY pubdate DESC 
            LIMIT 0, {$rowNum}";
    $result = $dsql->GetAll($sql);
    $html = '<ul>';
    if (!empty($result)) {
        foreach ($result as $article) {
            $url = GetArcUrl($article['id'], $article['typeid']);
            $html .= "<li><a href='{$url}'>{$article['title']}</a></li>";
        }
    } else {
        $html .= '<li>暂无推荐文章</li>';
    }
    $html .= '</ul>';
    return $html;
}

然后在文章详情页的PHP处理文件(通常是 /plus/view.php)中调用这个函数并赋值给模板。

打开 /plus/view.php,找到 $Fields['templet'] 之前的位置,添加:

// ... view.php 中的其他代码 ...
// 引入自定义函数文件
require_once(DEDEINC.'/helpers/extend.helper.php');
// 获取同分类文章推荐HTML
$Fields['same_category_list'] = GetSameCategoryHtmlList($aid, $typeid, 5);
// ... view.php 中的其他代码 ...

在模板 article_article.htm 中直接输出变量:

<h3>同分类文章推荐</h3>
{dede:field.name='same_category_list'/}

总结与安全建议

方法 优点 缺点 推荐度
{dede:php} 灵活,功能强大 安全风险高,模板逻辑混乱,不易维护 ⭐ (不推荐,除非万不得已)
{dede:sql} 安全,简洁,模板干净 复杂SQL和多表查询时稍显笨拙 ⭐⭐⭐⭐⭐ (强烈推荐)
修改PHP源文件 最规范,最安全,逻辑与视图分离,可复用性强 需要修改PHP文件,对新手有门槛 ⭐⭐⭐⭐⭐ (大型项目或复杂逻辑首选)

核心安全建议:

  1. 永远不要相信用户输入:所有来自URL、表单或模板变量的数据,在使用前必须进行过滤(如intval(), htmlspecialchars())。
  2. 优先使用DedeCMS提供的标签:如 {dede:sql},它们已经内置了安全机制。
  3. 避免在模板中写复杂逻辑:模板的职责是展示数据,而不是处理数据,复杂的业务逻辑应该放在PHP文件中。
  4. 使用参数化查询:如果必须使用原生PHP查询,尽量使用 $dsql->Execute('me', "SELECT ... WHERE id=?", array($id)) 这种预处理语句的方式,这是最安全的SQL执行方式。
-- 展开阅读全文 --
头像
织梦 common.inc.php 如何安全配置防注入?
« 上一篇 今天
Visual C学C语言,该选哪个版本?
下一篇 » 今天

相关文章

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