DedeCMS 的数据库操作核心是封装在 include/dedesql.class.php 文件中的 DEDESQL 类,这个类基于 PHP 的 mysqli 扩展,提供了简单易用的方法来执行查询、获取数据、更新数据等。
核心类:DEDESQL
在进行任何数据库操作之前,你首先需要实例化这个类。
// 引入核心类文件 require_once(DEDEINC.'/dedesql.class.php'); // 实例化一个对象 $dsql = new DEDESQL(false); // false 表示不使用长连接
注意:在 DedeCMS 的很多文件中,你不需要手动 include 和 new,因为系统已经为你创建了一个全局对象 $db,但在自定义的 PHP 页面或插件中,你可能需要自己创建。
常用数据库操作方法
DEDESQL 类提供了一系列方法,覆盖了 CRUD(增删改查)操作。
执行 SQL 语句 (ExecuteOneQuery 和 Execute)
这是最基础的方法,用于执行任何 SQL 语句。
ExecuteOneQuery($sql): 执行一个 SQL 语句,并返回一个单一的结果(SELECT COUNT(*)的结果),适用于不需要遍历结果的查询。Execute($sql): 执行一个 SQL 语句,并返回一个资源句柄或结果集,通常与GetOne()、GetArray()等方法配合使用。
示例:查询文章总数
$sql = "SELECT COUNT(*) AS total FROM dede_archives"; $total = $dsql->GetOne($sql); // GetOne 内部就是调用 Execute 并获取第一行第一列 echo "网站文章总数为:".$total['total'];
查询数据
这是最常用的操作,用于从数据库中获取数据。
a. 获取单行数据 (GetOne)
当你只需要查询一条记录时使用,返回一个关联数组。
语法: GetOne($sql)
示例:获取 ID 为 1 的文章信息
$sql = "SELECT * FROM dede_archives WHERE id = 1";
$arcRow = $dsql->GetOne($sql);
if(is_array($arcRow)) {
echo "文章标题: " . $arcRow['title'];
echo "文章内容: " . $arcRow['body'];
} else {
echo "文章不存在!";
}
b. 获取多行数据 (GetArray)
当你需要查询多条记录时使用,返回一个二维数组。
语法: GetArray($sql)
示例:获取最新的 10 篇文章
$sql = "SELECT id, title, pubdate FROM dede_archives ORDER BY pubdate DESC LIMIT 10";
$arts = $dsql->GetArray($sql);
if(is_array($arts)) {
foreach($arts as $row) {
echo "<a href='/view.php?aid=".$row['id']."'>".$row['title']."</a> (发布于: ".date('Y-m-d', $row['pubdate']).")<br>";
}
}
c. 遍历结果集 (Execute + GetArray)
这个方法更灵活,适合处理非常大的结果集,因为它可以分批读取数据,避免内存溢出。
语法:
$dsql->Execute('me', $sql);// 执行查询,'me' 是一个别名while($row = $dsql->GetArray('me')) { ... }// 循环获取每一行
示例:分页显示所有栏目
$sql = "SELECT id, typename, reid FROM dede_arctype";
$dsql->Execute('ct', $sql); // 使用 'ct' 作为查询别名
while($row = $dsql->GetArray('ct')) {
echo "栏目ID: " . $row['id'] . ", 名称: " . $row['typename'] . "<br>";
}
插入数据 (ExecuteNoneQuery)
用于执行 INSERT、UPDATE、DELETE 等 不需要返回结果集 的 SQL 语句。
语法: ExecuteNoneQuery($sql)
返回值: 成功返回受影响的行数,失败返回 false。
示例:添加一个新文章
$title = "这是一篇新测试文章";
$content = "这是文章的详细内容。";
$pubdate = time();
$arcid = 0; // 文章ID,由数据库自动生成
$sql = "INSERT INTO dede_archives (title, typeid, pubdate, senddate, arcrank, ismake, mid, click, money, body)
VALUES ('$title', 1, $pubdate, $pubdate, 0, 1, 1, 0, 0, '$content')";
$rs = $dsql->ExecuteNoneQuery($sql);
if($rs) {
// 获取刚刚插入的文章ID
$arcid = $dsql->GetLastID(); // 关键!
echo "文章添加成功,ID 为: " . $arcid;
} else {
echo "文章添加失败!";
}
重要提示:ExecuteNoneQuery 执行后,可以使用 $dsql->GetLastID() 来获取最后一条 INSERT 操作产生的自增 ID。
更新数据 (ExecuteNoneQuery)
更新数据和插入数据使用同一个方法,只是 SQL 语句不同。
示例:更新 ID 为 10 的文章标题
$new_title = "更新后的文章标题";
$aid = 10;
$sql = "UPDATE dede_archives SET title = '$new_title' WHERE id = $aid";
$rs = $dsql->ExecuteNoneQuery($sql);
if($rs > 0) { // 受影响的行数大于0,表示更新成功
echo "文章标题更新成功!";
} else {
echo "文章标题更新失败或没有变化!";
}
删除数据 (ExecuteNoneQuery)
同样使用 ExecuteNoneQuery。
示例:删除 ID 为 15 的文章
$aid = 15;
// 注意:删除文章通常需要同时删除相关表的数据,如 dede_archives, dede_addonarticle, dede_arctiny 等
// 这里仅作示例,实际操作需谨慎
$sql = "DELETE FROM dede_archives WHERE id = $aid";
$rs = $dsql->ExecuteNoneQuery($sql);
if($rs > 0) {
echo "文章删除成功!";
} else {
echo "文章删除失败!";
}
安全与最佳实践
直接拼接 SQL 语句是非常危险的,容易受到 SQL 注入攻击,DedeCMS 提供了两种安全的方式来处理数据。
使用 DEDESQL 内置的过滤方法
DEDESQL 类提供了 ReplaceText() 和 AddSlashes() 方法来过滤和转义数据。
AddSlashes($str): 对字符串进行转义,防止 SQL 注入。ReplaceText($str): 不仅转义,还会替换掉一些危险的标签和字符,更安全。
示例(安全地插入数据)
$title = "'; DROP TABLE dede_archives; --"; // 模拟一个恶意输入
$content = "安全的内容";
// 使用 ReplaceText 进行过滤
$safe_title = $dsql->ReplaceText($title);
$safe_content = $dsql->ReplaceText($content);
$sql = "INSERT INTO dede_archives (title, body) VALUES ('$safe_title', '$safe_content')";
$dsql->ExecuteNoneQuery($sql);
echo "数据已安全插入。";
使用 DEDESQL 的参数化查询 (SelectSql)
这是最推荐的方式,可以完全避免 SQL 注入,它通过 Prepare 语句实现。
语法:
$dsql->SetQuery($sql);// 设置 SQL 模板,用 作为占位符$dsql->Bind('变量名', $变量值);// 绑定参数$dsql->Execute();// 执行
示例(安全地查询)
$aid = 10; // 假设这个值来自用户输入
// 1. 设置查询语句,#aid 是一个占位符
$dsql->SetQuery("SELECT * FROM dede_archives WHERE id = #aid");
// 2. 绑定参数
$dsql->Bind('aid', $aid);
// 3. 执行查询
$dsql->Execute();
// 4. 获取结果
$arcRow = $dsql->GetArray();
if(is_array($arcRow)) {
echo "找到文章: " . $arcRow['title'];
} else {
echo "未找到文章。";
}
这种方式下,$aid 的值会被自动处理,即使包含恶意 SQL 代码也不会被执行。
常用查询技巧
获取某个表的所有字段
$dsql->GetFields($table_name); 可以获取指定表的结构信息(字段名、类型等)。
$fields = $dsql->GetFields('dede_archives');
print_r($fields);
事务处理
对于需要多个 SQL 语句同时成功或同时失败的操作(比如转账),可以使用事务。
$dsql->Execute('tr1', "START TRANSACTION"); // 开始事务
$sql1 = "UPDATE dede_member SET scores = scores - 100 WHERE mid = 1";
$sql2 = "UPDATE dede_member SET scores = scores + 100 WHERE mid = 2";
$dsql->ExecuteNoneQuery($sql1);
// 模拟一个错误
// if(true) die(); // 如果这里发生错误,下面的代码不会执行
$dsql->ExecuteNoneQuery($sql2);
$dsql->Execute('tr1', "COMMIT"); // 提交事务
echo "事务提交成功!";
// 如果中途出错,应该回滚
// $dsql->Execute('tr1', "ROLLBACK");
| 操作类型 | 推荐方法 | 说明 |
|---|---|---|
| 执行任意SQL | $dsql->ExecuteOneQuery() / $dsql->Execute() |
用于执行不需要返回结果集或需要手动遍历的SQL。 |
| 查询单条 | $dsql->GetOne($sql) |
返回一个关联数组,适合获取单条记录。 |
| 查询多条 | $dsql->GetArray($sql) |
返回一个二维数组,适合获取多条记录。 |
| 增/删/改 | $dsql->ExecuteNoneQuery($sql) |
执行 INSERT, UPDATE, DELETE,返回受影响行数。 |
| 安全查询 | $dsql->SetQuery() + $dsql->Bind() |
强烈推荐,使用参数化查询,防止SQL注入。 |
| 获取自增ID | $dsql->GetLastID() |
在 ExecuteNoneQuery 执行 INSERT 后使用。 |
| 数据过滤 | $dsql->ReplaceText() / $dsql->AddSlashes() |
在手动拼接SQL时使用,防止SQL注入。 |
掌握这些方法和最佳实践,你就可以在 DedeCMS 中安全、高效地进行各种数据库操作了。
