联动,也叫级联,指的是表单中一个字段的选项会根据另一个字段的选择而动态改变,最常见的例子就是“省-市-区”三级联动。

(图片来源网络,侵删)
DedeCMS本身不直接提供可视化的联动表单创建工具,所以我们需要通过修改模板文件和少量PHP代码来实现,下面我将以最常见的“省份-城市”二级联动为例,为你提供一个详细、可操作的步骤指南。
核心思路
实现联动的核心思路是:
- 数据准备:创建两个数据表,一个存省份,一个存城市,并通过
province_id字段将它们关联起来。 - 前端HTML:在模板中创建两个
<select>下拉框,一个用于省份,一个用于城市,使用 jQuery 监听省份下拉框的change事件。 - 后端交互:当省份选择改变时,通过 jQuery 的
$.ajax方法向一个专门处理联动的PHP文件发送请求,并传递所选省份的ID。 - PHP处理:联动PHP文件接收省份ID,查询对应的数据库,获取城市列表,并将城市数据以JSON格式返回。
- 前端渲染:jQuery 接收返回的JSON数据,动态生成
<option>选项,并填充到城市下拉框中。
详细步骤
第一步:准备数据库
我们需要在DedeCMS的数据库中创建两个表来存储省份数据和城市数据。
创建省份表 dede_provinces

(图片来源网络,侵删)
CREATE TABLE `dede_provinces` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '省份ID', `name` varchar(50) NOT NULL COMMENT '省份名称', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
创建城市表 dede_cities
CREATE TABLE `dede_cities` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '城市ID', `province_id` int(10) unsigned NOT NULL COMMENT '所属省份ID', `name` varchar(50) NOT NULL COMMENT '城市名称', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
插入示例数据
向这两个表中插入一些测试数据。
省份表示例数据:

(图片来源网络,侵删)
INSERT INTO `dede_provinces` (`id`, `name`) VALUES (1, '广东省'), (2, '江苏省'), (3, '浙江省');
城市表示例数据:
INSERT INTO `dede_cities` (`id`, `province_id`, `name`) VALUES (1, 1, '广州市'), (2, 1, '深圳市'), (3, 1, '珠海市'), (4, 2, '南京市'), (5, 2, '苏州市'), (6, 2, '无锡市'), (7, 3, '杭州市'), (8, 3, '宁波市'), (9, 3, '温州市');
第二步:创建Dede自定义表单
- 登录DedeCMS后台。
- 进入【核心】 -> 【内容模型管理】 -> 【自定义表单】。
- 点击【增加新表单】,填写表单信息:
- 表单名称:
联动表单示例(可以任意) - 数据表:
dede_addonlinkage(系统会自动生成,也可以自定义,但要和下面代码中的$dsql->SetQuery保持一致) - 默认表单模板:
default(保持默认) - 列表模板:
list_linkage.htm(保持默认) - 普通模板:
post_linkage.htm(保持默认) - 成功提示:
提交成功!
- 表单名称:
- 点击【确定】。
- 在字段管理中,增加两个字段:
- 字段名:
province,字段类型:下拉菜单,选项填写:广东省,江苏省,浙江省(这里先手动填上,后面会被JS覆盖)。 - 字段名:
city,字段类型:下拉菜单,选项填写:请先选择省份。
- 字段名:
第三步:创建联动处理文件
我们需要一个PHP文件来处理AJAX请求并返回JSON数据。
- 在你的DedeCMS根目录下创建一个新文件,命名为
ajax_getcity.php。 - 将以下代码复制到
ajax_getcity.php文件中:
<?php
require_once (dirname(__FILE__) . "/include/common.inc.php");
require_once DEDEINC.'/datalistcp.class.php';
// 获取通过POST传递过来的省份ID
$province_id = isset($_POST['province_id']) ? intval($_POST['province_id']) : 0;
// 初始化城市数组
$cities = array();
if ($province_id > 0) {
// 查询对应省份下的所有城市
$dsql->SetQuery("SELECT id, name FROM dede_cities WHERE province_id = {$province_id} ORDER BY id ASC");
$dsql->Execute('city');
while ($row = $dsql->GetArray('city')) {
$cities[] = $row;
}
}
// 设置响应头为JSON格式
header('Content-Type: application/json');
// 将城市数组以JSON格式输出
echo json_encode($cities);
exit();
?>
代码解释:
- 引入了DedeCMS的必要配置文件。
- 接收前端POST过来的
province_id。 - 使用
$dsql查询dede_cities表,找出province_id匹配的所有城市。 - 使用
json_encode()将PHP数组转换为JSON字符串,这是前端JavaScript可以直接识别的格式。 header('Content-Type: application/json');告诉浏览器返回的是JSON数据,这是一个好习惯。
第四步:修改前端模板文件
这是最关键的一步,我们要在表单模板中引入jQuery并编写联动逻辑。
-
找到你的自定义表单模板文件,路径通常是
templets/plus/post_linkage.htm(如果第二步中你没有修改模板名)。 -
打开这个文件,找到
<form>标签,并在里面定位到省份和城市的下拉菜单,它们看起来可能像这样:<select name="province" id="province"> <option value='0'>请选择省份</option> <option value='1'>广东省</option> <option value='2'>江苏省</option> <option value='3'>浙江省</option> </select> <select name="city" id="city"> <option value='0'>请选择城市</option> </select> -
修改这两个下拉框,并加入我们的JS代码,修改后的
post_linkage.htm文件内容如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">联动表单提交</title>
<!-- 引入jQuery库,DedeCMS默认在 /include/js/jquery.js -->
<script src="/include/js/jquery/jquery.js"></script>
</head>
<body>
<h2>联动表单示例</h2>
<form action='plus/diy.php' enctype='multipart/form-data' method='post'>
<input type='hidden' name='dede_fields' value='province,text;city,text' />
<input type='hidden' name='dede_fieldshash' value='<?php echo $_SESSION['dede_fieldshash'];?>' />
<div>
<label for="province">省份:</label>
<!-- 省份下拉框,id="province" 是关键 -->
<select name="province" id="province">
<option value="0">请选择省份</option>
{dede:global name='list' runphp='yes'}
$dsql = new DedeSql(false);
$sql = "SELECT id, name FROM dede_provinces ORDER BY id ASC";
$dsql->SetQuery($sql);
$dsql->Execute('pro');
$options = '';
while($row = $dsql->GetArray('pro')){
$options .= "<option value='{$row['id']}'>{$row['name']}</option>";
}
@me=$options;
{/dede:global}
</select>
</div>
<div style="margin-top: 10px;">
<label for="city">城市:</label>
<!-- 城市下拉框,id="city" 是关键,初始为空 -->
<select name="city" id="city">
<option value="0">请先选择省份</option>
</select>
</div>
<div style="margin-top: 10px;">
<button type="submit">提交</button>
</div>
</form>
<script type="text/javascript">
$(function(){
// 监听省份下拉框的改变事件
$("#province").change(function(){
// 获取当前选中的省份ID
var province_id = $(this).val();
var city_select = $("#city");
// 如果省份ID为0,则清空城市下拉框并返回
if(province_id == 0){
city_select.empty().append("<option value='0'>请先选择省份</option>");
return;
}
// 显示一个加载提示(可选)
city_select.empty().append("<option value='0'>加载中...</option>");
// 发起AJAX请求
$.ajax({
url: "/ajax_getcity.php", // 我们创建的联动处理文件
type: "POST",
data: { "province_id": province_id },
dataType: "json", // 期望返回的数据类型是JSON
success: function(data){
// 请求成功后,清空城市下拉框
city_select.empty().append("<option value='0'>请选择城市</option>");
// 遍历返回的JSON数据,生成option并添加到城市下拉框
$.each(data, function(i, item){
city_select.append("<option value='" + item.id + "'>" + item.name + "</option>");
});
},
error: function(){
// 请求失败时,显示错误信息
city_select.empty().append("<option value='0'>加载失败,请重试</option>");
}
});
});
});
</script>
</body>
</html>
代码解释:
- 引入jQuery:
<script src="/include/js/jquery/jquery.js"></script>加载DedeCMS自带的jQuery库。 - 省份下拉框: 使用
{dede:global}循环标签从dede_provinces表中动态读取省份数据,并生成<option>,这样比手动维护更方便。 - 城市下拉框: 初始时只有一个默认选项,内容将由JS动态填充。
- jQuery联动逻辑:
$("#province").change(function(){...}): 当省份选择改变时,触发这个函数。var province_id = $(this).val(): 获取被选中的省份的value值。$.ajax({...}): 发起异步请求。url: 指向我们创建的ajax_getcity.php。data: 将province_id作为POST数据发送。dataType: "json": 告诉jQuery我们期待服务器返回JSON。success: function(data){...}: 请求成功后的回调函数。data就是服务器返回的JSON数组。$.each(data, ...): 遍历data数组,为每个城市创建一个<option>并添加到城市下拉框中。error: 请求失败时的处理。
第五步:测试
- 清理一下DedeCMS的缓存:后台 -> 系统 -> 站点清理 -> 清理所有缓存。
- 在前台访问你的自定义表单页面(
plus/post.php?diyid=你的表单ID)。 - 你应该能看到省份下拉框里有“广东省”、“江苏省”等选项。
- 当你选择“广东省”时,城市下拉框会自动加载“广州市”、“深圳市”、“珠海市”。
- 当你切换省份时,城市列表也会相应改变。
至此,一个完整的DedeCMS自定义表单联动功能就实现了。
总结与注意事项
- 安全性:
ajax_getcity.php文件接收了province_id,虽然我们用了intval()进行了类型转换和简单过滤,但在生产环境中,最好再做一些更严格的校验,防止SQL注入,DedeCMS的$dsql对象本身有安全机制,但养成好习惯总是好的。 - 三级及以上联动:如果要实现“省-市-区”三级联动,原理是一样的,你需要再创建一个区县表,在城市的
change事件中,去请求另一个处理区县的PHP文件,该文件接收city_id作为参数。 - 数据来源:如果你的省市区数据量很大,手动插入很麻烦,可以考虑从网上下载现成的SQL数据文件直接导入数据库。
- 模板标签:在模板中直接使用
{dede:global}循环数据库数据,比在后台手动填写选项更灵活、更易于维护。
希望这个详细的教程能帮助你成功实现DedeCMS的自定义表单联动功能!
