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

场景假设
假设我们要在文章详情页(article_article.htm)中,获取与当前文章同分类下的其他5篇文章,并显示它们的标题和链接。
使用 {dede:php} 标签(最直接,但需谨慎)
这是最直接的方法,允许你在模板中直接嵌入PHP代码。
修改模板配置文件
你需要确保你的模板配置文件( 打开你的模板PHP文件,找到类似 打开你的详情页模板文件, 代码解析: 这是DedeCMS官方推荐的、在模板中执行SQL查询的方法,它比 同样在 代码解析: 为什么推荐 对于非常复杂且需要多次复用的逻辑,最佳实践是修改DedeCMS的PHP源文件,然后在模板中调用。 在 在 你的模板文件 或者,如果你想让模板更简洁,可以在PHP文件里把HTML也处理好,然后只输出一个变量。 修改 然后在文章详情页的PHP处理文件(通常是 打开 在模板 核心安全建议:templets/plus/view_template.php 或 templets/default/article_article.php)中启用了 php
$cfg_fckphp = 'Y'; 的地方,确保PHP标签被允许,DedeCMS默认是允许的。在模板文件中编写代码
templets/default/article_article.htm,在你需要显示同分类文章的位置,插入如下代码:
<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} 标签(更安全,推荐){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: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}?
~var~) 自动防止了SQL注入。
修改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并赋值给模板变量
/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;
}
/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文件,对新手有门槛
⭐⭐⭐⭐⭐ (大型项目或复杂逻辑首选)
intval(), htmlspecialchars())。{dede:sql},它们已经内置了安全机制。$dsql->Execute('me', "SELECT ... WHERE id=?", array($id)) 这种预处理语句的方式,这是最安全的SQL执行方式。
