- 数据关联:将多个自定义表单关联起来,让一个表单的提交结果可以影响到另一个表单的数据,用户提交了“项目申请”表单后,自动在“项目进度”表单中创建一条对应记录。
- 内容关联:将自定义表单的提交结果与站点的文章、栏目等内容模型关联起来,实现表单提交后自动生成文章、关联到指定栏目等。
这两种关联都非常实用,可以极大地扩展 DedeCMS 的应用场景,下面我将分别讲解实现方法。

数据关联(一个表单影响另一个表单)
这是最常见的需求。
- 报名流程:用户先填写“预报名”表单,管理员审核通过后,系统自动在“正式报名”表单中为其创建一条记录。
- 订单流程:用户提交“购物车”表单后,系统自动在“订单”表单中生成一条订单记录。
实现原理
核心思路是:在第一个表单(源表单)的提交处理文件中,加入代码来操作第二个表单(目标表单)的数据。
DedeCMS 的自定义表单数据是直接写入数据库的 dede_sysform 和 dede_sysformplus(附加字段)表中的,我们可以通过 SQL 插入语句来实现关联。
实现步骤(以“预报名” -> “正式报名”为例)
假设我们有两个自定义表单:

- 源表单:
pre_apply(预报名) - 目标表单:
formal_apply(正式报名)
第一步:创建两个自定义表单
在后台“核心” -> “内容模型管理” -> “自定义表单”中,分别创建 pre_apply 和 formal_apply 两个表单,并设计好各自的字段,它们都可能有 name, tel, email 等字段。
第二步:找到源表单的提交处理文件
- 进入
plus/diy.php文件,这是所有自定义表单的统一处理入口。 - 在文件中找到处理成功后的逻辑部分,通常在
if($dsql->Execute('me')){ ... }这个代码块之后。
第三步:在 plus/diy.php 中添加关联代码

在 diy.php 文件中,找到处理成功后的位置(在 $goto = "{$cfg_cmspath}/plus/diy.php?action=list&diyid={$diy->diyid}"; 这行代码之前),添加如下代码:
// --- 在这里添加关联代码 ---
// 1. 获取源表单提交的所有数据
// $diy->table 是当前表单的数据表名,如 dede_sysform_1
$source_table = $diy->table;
$source_data = array();
// 从 $_POST 中获取数据(注意:需要过滤不安全的字段,这里仅为示例)
foreach ($_POST as $key => $value) {
// 简单判断,只处理我们需要的字段,防止SQL注入
if (in_array($key, array('name', 'tel', 'email', 'company'))) {
$source_data[$key] = addslashes($value);
}
}
// 2. 获取目标表单的信息
// 假设“正式报名”表单在后台的ID是 2
$target_diyid = 2;
$target_diymodel = new Archivemodel();
$target_diymodel->init($target_diyid);
$target_table = $target_diymodel->table; // 目标表的数据表名,如 dede_sysform_2
// 3. 向目标表单插入数据
if (!empty($source_data)) {
$sql = "INSERT INTO `{$target_table}` (`id`, `ifcheck`, `typeid`, `arcrank`, `title`, `senddate`, `mid`, `ip`) VALUES ";
$sql .= "(NULL, 0, 0, 0, '', " . time() . ", 1, '" . GetIP() . "');";
// 先插入主表数据,获取新记录的ID
$dsql->ExecuteNoneQuery($sql);
$new_id = $dsql->GetLastID();
// 再向附加表插入数据
$plus_sql = "INSERT INTO `{$target_table}_plus` (`aid`";
$values_sql = " VALUES ({$new_id}";
foreach ($source_data as $field => $value) {
$plus_sql .= ", `{$field}`";
$values_sql .= ", '{$value}'";
}
$plus_sql .= ")";
$values_sql .= ")";
$final_plus_sql = $plus_sql . $values_sql;
if ($dsql->ExecuteNoneQuery($final_plus_sql)) {
// 关联成功,可以在这里记录日志或进行其他操作
// echo "关联成功!";
} else {
// 关联失败
// echo "关联失败!";
}
}
// --- 关联代码结束 ---
// 原来的跳转逻辑
$goto = "{$cfg_cmspath}/plus/diy.php?action=list&diyid={$diy->diyid}";
代码解释:
- 获取源数据:遍历
$_POST,获取用户提交的表单数据。addslashes()是为了防止SQL注入。 - 获取目标表单信息:通过目标表单的
diyid(在后台表单列表中可以看到ID),初始化一个模型对象,并获取其数据表名$target_table。 - 插入数据:
- 先向主表 (
dede_sysform_x) 插入一条空记录,并获取其自增ID$new_id。 - 再向附加表 (
dede_sysform_x_plus) 中插入具体的字段数据,并将aid字段设置为刚才获取的$new_id,从而将附加数据与主表记录关联起来。
- 先向主表 (
重要提示:
- 安全性:直接使用
$_POST数据有SQL注入风险,上述代码中的in_array是一种简单的过滤,在生产环境中建议使用更严格的过滤或参数化查询。 diyid:务必获取正确的目标表单的diyid。- 字段名:确保
$source_data中的键(字段名)与目标表单的字段名完全一致。
内容关联(表单数据生成文章或关联内容)
这个需求也很常见,
- 投稿功能:用户通过自定义表单提交文章稿件,提交后直接在指定栏目生成一篇待审核的文章。
- 用户反馈:用户提交反馈后,自动生成一篇包含反馈内容的通知文章,发送给管理员。
实现原理
与数据关联类似,我们也是在 plus/diy.php 中操作,但这次不是操作 dede_sysform 表,而是操作 DedeCMS 的核心内容表,如 dede_archives (文章主表)、dede_addonarticle (文章附加表) 等。
实现步骤(以“投稿”为例)
第一步:创建自定义表单
创建一个名为 article_contribute 的自定义表单,字段可以包括 title (文章标题), author (作者), source (来源), content (文章内容), typeid (投稿栏目) 等。
第二步:修改 plus/diy.php
在 diy.php 的成功处理部分,添加生成文章的代码。
// --- 在这里添加生成文章的代码 ---
// 1. 获取表单提交的数据
$title = isset($_POST['title']) ? addslashes($_POST['title']) : '无标题';
$author = isset($_POST['author']) ? addslashes($_POST['author']) : '匿名';
$content = isset($_POST['content']) ? $_POST['content'] : ''; // 文章内容通常不需要 addslashes
$target_typeid = isset($_POST['typeid']) ? intval($_POST['typeid']) : 0; // 目标栏目ID
// 2. 准备文章数据
$arc = array(
'typeid' => $target_typeid,
'sortrank' => time(),
'flag' => '',
'ismake' => -1, // -1表示不生成HTML,由管理员后台生成
'channel' => 1, // 1表示文章模型
'arcrank' => 0, // 0表示待审核
'click' => 0, => $title,
'shorttitle' => '',
'color' => '',
'writer' => $author,
'source' => $author, // 来源默认为作者
'pubdate' => time(),
'senddate' => time(),
'mid' => 1, // 管理员ID
'description' => cn_substr(html2text($content), 200), // 从内容中提取摘要
);
// 3. 获取DedeCMS主数据库连接
$dsql = DedeInclude::getDB();
// 4. 插入到主表 dede_archives
$arcid = $dsql->GetLastID(); // 先获取一个ID用于附加表
$inquery = $dsql->ExecuteNoneQuery2("INSERT INTO `dede_archives`(id, typeid, sortrank, flag, ismake, channel, arcrank, click, title, shorttitle, color, writer, source, pubdate, senddate, mid, description) VALUES ('$arcid', '{$arc['typeid']}', '{$arc['sortrank']}', '{$arc['flag']}', '{$arc['ismake']}', '{$arc['channel']}', '{$arc['arcrank']}', '{$arc['click']}', '{$arc['title']}', '{$arc['shorttitle']}', '{$arc['color']}', '{$arc['writer']}', '{$arc['source']}', '{$arc['pubdate']}', '{$arc['senddate']}', '{$arc['mid']}', '{$arc['description']}');");
if($inquery)
{
// 5. 插入到附加表 dede_addonarticle
$addQuery = "INSERT INTO `dede_addonarticle` (`aid`, `typeid`, `body`, `userip`) VALUES ('$arcid', '{$arc['typeid']}', '$content', '" . GetIP() . "')";
$dsql->ExecuteNoneQuery($addQuery);
// 可选:更新主表的ID
$dsql->ExecuteNoneQuery("UPDATE `dede_archives` SET id = LAST_INSERT_ID() WHERE id = '$arcid'");
// 可选:给用户一个成功提示,并告知文章已生成
// $msg = '投稿成功!您的文章已提交,请等待管理员审核。';
// $gourl = "../.."; // 跳转到首页
// ShowMsg($msg, $gourl, 0, 2000);
// exit();
}
// --- 生成文章代码结束 ---
// 原来的跳转逻辑
$goto = "{$cfg_cmspath}/plus/diy.php?action=list&diyid={$diy->diyid}";
代码解释:
- 获取数据:从
$_POST中获取文章标题、作者、内容和目标栏目ID。 - 准备数据数组:按照
dede_archives表的结构,组织一个包含文章信息的数组。 - 插入主表:使用
$dsql->ExecuteNoneQuery2()将数据插入到dede_archives表,这个函数会自动处理ID。 - 插入附加表等长文本存放在附加表
dede_addonarticle中,通过LAST_INSERT_ID()获取主表刚刚插入记录的ID,然后将内容存入附加表。 - 状态控制:
arcrank => 0:文章状态为“待审核”,管理员需要在后台审核后才能显示。ismake => -1:不自动生成HTML文件,避免垃圾页面产生。
总结与最佳实践
| 关联类型 | 核心原理 | 修改文件 | 关键点 |
|---|---|---|---|
| 数据关联 | 在源表单处理逻辑中,向目标表单的数据库表插入新记录。 | plus/diy.php |
准确获取目标表单的 diyid 和表名。分别操作主表和附加表。 注意SQL注入风险。 |
重要提醒:
- 备份:在修改
plus/diy.php文件之前,务必先备份原文件! - 测试:在测试环境充分测试功能,确认无误后再部署到生产环境。
- 代码风格:以上代码为示例,实际开发中应考虑使用更健壮的类和方法来操作数据库,以提高代码的可读性和安全性。
通过以上方法,你就可以灵活地实现 DedeCMS 自定义表单的各种复杂关联需求了。
