联动筛选,也叫联动菜单,通常用于商品、房产、招聘等需要根据多个维度(如品牌、价格、区域、学历等)进行筛选的场景,用户点击一个菜单项,页面会根据所选条件动态刷新,显示筛选后的结果。

(图片来源网络,侵删)
我们将以一个“笔记本电脑”的商品筛选为例,包含以下筛选条件:
- 品牌 (苹果, 联想, 华硕, 惠普)
- 价格区间 (5000以下, 5000-7000, 7000-10000, 10000以上)
- 核心配置 (i5, i7, i9)
第一步:准备工作
在开始之前,请确保你已经:
- 安装并运行 DedeCMS。
- 模型:在后台
后台 -> 核心 -> 内容模型管理中,为“笔记本电脑”创建一个专门的内容模型,这个模型将包含我们需要的自定义字段,如brand(品牌),price_range(价格区间),cpu(核心配置)。 - 添加了自定义字段:在创建或编辑内容模型时,添加三个字段:
brand:字段类型为联动类型,绑定到“品牌”的联动类别。price_range:字段类型为联动类型,绑定到“价格区间”的联动类别。cpu:字段类型为联动类型,绑定到“核心配置”的联动类别。
- 录入测试数据:发布一些“笔记本电脑”的文章,并为每篇文章填写这些联动字段的值。
第二步:创建联动类别
这是联动筛选的核心,我们需要为每个筛选条件创建一个独立的联动类别。
-
进入联动类别管理:
后台 -> 核心 -> 联动类型。
(图片来源网络,侵删) -
创建“品牌”联动类别:
- 点击
增加联动类别。 - 类别名称:
品牌 - 栏目使用:选择你存放“笔记本电脑”的栏目。
- 是否开启:
是 - 内容显示前缀:
<span class="label">品牌:</span> - 内容显示后缀:
<br /> - 点击
提交。 - 增加子栏目:在刚创建的“品牌”类别下,添加子项:
苹果(需要填写对应的id,系统会自动生成,1)联想(2)华硕(3)惠普(4)
- 点击
-
创建“价格区间”联动类别:
- 同样方法,创建一个名为
价格区间的联动类别,并关联到你的栏目。 - 增加子项:
5000以下(1)5000-7000(2)7000-10000(3)10000以上(4)
- 同样方法,创建一个名为
-
创建“核心配置”联动类别:
- 创建名为
核心配置的联动类别。 - 增加子项:
i5(1)i7(2)i9(3)
- 创建名为
注意:创建时,请确保每个联动类别都正确关联到了你的内容模型所在的栏目。

(图片来源网络,侵删)
第三步:创建列表模板
这是用户看到并交互的页面,我们将创建一个包含筛选表单和结果列表的模板文件,laptop_list.htm。
- 创建模板文件:在你的模板目录(通常是
/templets/default/或你自定义的目录)下,新建一个文件laptop_list.htm。 - 编写模板代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">笔记本电脑列表 - DedeCMS联动筛选实例</title>
<style>
.filter-box { width: 200px; float: left; border: 1px solid #ccc; padding: 10px; margin-right: 20px; }
.filter-box h3 { margin-top: 0; }
.filter-box .filter-item { margin-bottom: 10px; }
.filter-box a { display: block; padding: 5px; text-decoration: none; color: #333; }
.filter-box a:hover, .filter-box a.active { background-color: #f0f0f0; font-weight: bold; }
.content-list { float: left; width: calc(100% - 240px); }
.content-list li { list-style: none; border-bottom: 1px solid #eee; padding: 15px 0; }
</style>
</head>
<body>
<h1>笔记本电脑列表</h1>
<!-- 筛选表单 -->
<div class="filter-box">
<h3>品牌筛选</h3>
<div class="filter-item">
{dede:channelartlist typeid='0' typeid2='0'}
<a href="{dede:field name='typeurl'/}">全部</a>
{dede:son typeid='0'}
<a href="[field:typelink/]">[field:typename/]</a>
{/dede:son}
{/dede:channelartlist}
</div>
<h3>价格区间</h3>
<div class="filter-item">
{dede:global name='price_filter'/}
</div>
<h3>核心配置</h3>
<div class="filter-item">
{dede:global name='cpu_filter'/}
</div>
</div>
<!-- 内容列表 -->
<div class="content-list">
<ul>
{dede:list pagesize='10'}
<li>
<h2><a href="[field:arcurl/]">[field:title/]</a></h2>
<p>品牌:[field:brand function='GetInfos(@me, 0)'/]</p>
<p>价格:[field:price_range function='GetInfos(@me, 0)'/]</p>
<p>配置:[field:cpu function='GetInfos(@me, 0)'/]</p>
</li>
{/dede:list}
</ul>
{dede:pagelist listsize='4'/}
</div>
</body>
</html>
代码解析:
{dede:channelartlist ...}和{dede:son ...}:这部分是用来动态生成联动菜单的。typeid='0'表示从根目录开始读取你创建的联动类别。{dede:global name='price_filter'/}和{dede:global name='cpu_filter'/}:这两个是关键,它们不是固定的模板标签,而是我们将在 PHP 代码中动态生成的筛选链接,并赋值给这两个全局变量。[field:brand function='GetInfos(@me, 0)'/]:这是在列表页显示联动字段的值。GetInfos函数可以将联动项的ID转换为可读的名称。0代表联动类别ID,你需要根据实际情况修改。
第四步:编写 PHP 逻辑文件
这是实现筛选功能的核心,当用户点击筛选链接时,PHP 文件会接收参数,并重新构建查询。
- 创建 PHP 文件:在
/include/目录下,创建一个名为laptop_list.php的文件。 - 编写 PHP 代码:
<?php
require_once(dirname(__FILE__)."/config.php");
require_once(DEDEINC."/arc.listview.php");
// 获取筛选参数
$brand = isset($_GET['brand']) ? (int)$_GET['brand'] : 0;
$price_range = isset($_GET['price_range']) ? (int)$_GET['price_range'] : 0;
$cpu = isset($_GET['cpu']) ? (int)$_GET['cpu'] : 0;
// 构建额外的SQL查询条件
$addSql = " WHERE arc.arcrank > -1 ";
// 根据品牌筛选
if ($brand > 0) {
$addSql .= " AND arc.addfield LIKE '%\"{$brand}\"%' ";
}
// 根据价格区间筛选
if ($price_range > 0) {
$addSql .= " AND arc.addfield LIKE '%\"{$price_range}\"%' ";
}
// 根据核心配置筛选
if ($cpu > 0) {
$addSql .= " AND arc.addfield LIKE '%\"{$cpu}\"%' ";
}
// --- 生成筛选菜单的HTML ---
// 品牌菜单
$brand_filter = '';
$brand_arr = array(1 => '苹果', 2 => '联想', 3 => '华硕', 4 => '惠普');
foreach ($brand_arr as $id => $name) {
$active_class = ($brand == $id) ? 'active' : '';
$url = $brand == $id ? 'javascript:void(0);' : "laptop_list.php?brand={$id}";
$brand_filter .= "<a href='{$url}' class='{$active_class}'>{$name}</a>";
}
// 价格区间菜单
$price_filter = '';
$price_arr = array(1 => '5000以下', 2 => '5000-7000', 3 => '7000-10000', 4 => '10000以上');
foreach ($price_arr as $id => $name) {
$active_class = ($price_range == $id) ? 'active' : '';
$url = $price_range == $id ? 'javascript:void(0);' : "laptop_list.php?price_range={$id}";
$price_filter .= "<a href='{$url}' class='{$active_class}'>{$name}</a>";
}
// 核心配置菜单
$cpu_filter = '';
$cpu_arr = array(1 => 'i5', 2 => 'i7', 3 => 'i9');
foreach ($cpu_arr as $id => $name) {
$active_class = ($cpu == $id) ? 'active' : '';
$url = $cpu == $id ? 'javascript:void(0);' : "laptop_list.php?cpu={$id}";
$cpu_filter .= "<a href='{$url}' class='{$active_class}'>{$name}</a>";
}
// 将生成的HTML分配给模板全局变量
$GLOBALS['price_filter'] = $price_filter;
$GLOBALS['cpu_filter'] = $cpu_filter;
// --- 实例化ListView并显示 ---
$lv = new ListView();
$lv->PartView = "laptop_list"; // 模板文件名,不带.htm
$lv->AddSql = $addSql; // 附加的SQL条件
$lv->Display();
?>
代码解析:
- 获取参数:从
$_GET中获取用户点击的筛选条件ID。 - 构建
AddSql:这是最关键的一步,我们根据获取到的ID,拼接一个AND条件,添加到默认的查询中。arc.addfield是 DedeCMS 存储所有自定义字段值的字段,它是一个序列化的字符串,所以我们用LIKE '%\"{$id}\"%'来判断文章是否包含该联动项的ID。 - 生成筛选菜单:我们遍历预设的筛选选项数组,为每个选项生成一个
<a>标签,如果该选项当前被选中($id == $_GET['id']),则链接为javascript:void(0);防止页面刷新,并添加一个active类用于高亮显示。 - 分配全局变量:使用
$GLOBALS['var_name'] = 'value';将生成的筛选菜单HTML传递给模板。 - 实例化
ListView:这是 DedeCMS 用于列表页的类,我们设置好模板文件名和附加的SQL条件,然后调用Display()方法来渲染页面。
第五步:创建栏目并绑定
最后一步,将所有组件关联起来。
- 创建栏目:在后台
后台 -> 核心 -> 内容栏目管理中,创建一个新栏目,笔记本电脑”。 - 设置栏目属性:
- 模型:选择你第一步创建的“笔记本电脑”内容模型。
- 列表模板:选择
laptop_list.htm。 - 列表命名规则:保持默认或修改为
laptop_list_{page}.php。 - 列表目录:设置为
laptop_list。
- 保存。
访问你创建的“笔记本电脑”栏目列表页,你应该能看到左侧有动态生成的筛选菜单,点击不同的菜单项,右侧的列表内容会根据你的选择进行筛选。
进阶优化与注意事项
- URL 美化:上面的例子使用了
?id=x的形式,你可以使用 DedeCMS 的arcmulti标签或list标签的pagelink属性,结合伪静态规则,实现更美观的 URL,如/laptop/apple/或/laptop/price-5000-7000/,这需要修改 PHP 文件中的参数获取逻辑和 URL 生成逻辑。 - 性能:
LIKE '%...%'在数据量很大时可能会影响查询性能,对于大型电商网站,更优的方案是为联动字段建立额外的索引,或者使用JOIN查询,但这需要对 DedeCMS 的底层进行更深入的修改。 - AJAX 无刷新筛选:为了更好的用户体验,可以使用 jQuery 等前端库,将筛选菜单的
href改为javascript:void(0);,然后通过 AJAX 请求laptop_list.php并获取返回的列表 HTML,再用jQuery.html()方法更新页面,实现无刷新筛选,这需要修改 PHP 文件,使其能够判断请求类型(普通请求还是 AJAX 请求)并返回不同的内容(完整页面或仅列表部分)。
这个实例涵盖了 DedeCMS 联动筛选从准备到实现的全过程,希望能帮助你理解并应用到自己的项目中。
