- 添加自定义字段:在后台为你的模型(比如文章模型、产品模型)添加需要筛选的字段。
- 为字段填写数据:在前台发布内容时,为这些字段填写具体的值。
- 制作筛选表单:在前台模板中,制作一个包含筛选条件的表单(如下拉框、单选按钮等)。
- 修改列表页:修改列表页的PHP文件,使其能够接收和处理筛选条件。
- 修改列表页模板:修改列表页的HTML模板,使其能够显示筛选结果。
下面我们用一个“产品筛选”的例子来详细说明,假设我们要根据“产品品牌”和“产品价格区间”来筛选产品。

(图片来源网络,侵删)
第一步:添加自定义字段
- 登录织梦后台,进入【核心】 -> 【内容模型管理】。
- 找到你想要添加筛选功能的模型,文章模型】,点击后面的【字段管理】。
- 在字段管理页面,点击【添加新字段】。
- 字段名:填写一个英文字段名,
pf_brand(pf是product的缩写,避免冲突)。 - :填写一个中文名称,产品品牌”。
- 字段类型:选择
下拉菜单或单选按钮,这里我们选择下拉菜单。 - 字段值:填写选项,每行一个。
苹果 三星 华为 小米 - 其他选项:保持默认即可。
- 点击【保存】。
重复以上步骤,再添加一个“价格区间”字段,字段名可以设为 pf_price,字段类型选择 下拉菜单,字段值填写:
0-1000
1000-3000
3000-5000
5000以上
第二步:为内容填写自定义字段数据
- 进入【常规】 -> 【内容管理】,发布一篇新的文章(产品)。
- 在发布页面,你会看到刚才添加的“产品品牌”和“价格区间”字段。
- 为它们选择或填写相应的值。
- 发布文章,重复此操作,发布几篇不同品牌和价格的文章,以便后续测试筛选功能。
第三步:制作筛选表单
这是前端用户交互的部分,我们通常把它放在列表页的顶部。
打开你的列表页模板文件,一般是 templets/你的模板目录/list_article.htm。
在列表循环 dede:list 的前面,添加以下HTML代码:

(图片来源网络,侵删)
<!-- 筛选表单开始 -->
<form name="search" action="{dede:global.cfg_cmspath/}/plus/list.php" method="get">
<input type="hidden" name="tid" value="{dede:field name='id'/}" />
<!-- 品牌筛选 -->
<div>
<label for="pf_brand">品牌:</label>
<select name="pf_brand" id="pf_brand" onchange="document.search.submit();">
<option value="">全部品牌</option>
{dede:sql sql="SELECT distinct ctf.pf_brand FROM `dede_arctype` tp LEFT JOIN `dede_archives` a ON tp.id = a.typeid LEFT JOIN `dede_addonproduct` ctf ON a.id = ctf.id WHERE tp.reid = ~typeid~ AND ctf.pf_brand != ''"}
<option value="[field:pf_brand/]">[field:pf_brand/]</option>
{/dede:sql}
</select>
</div>
<!-- 价格筛选 -->
<div>
<label for="pf_price">价格区间:</label>
<select name="pf_price" id="pf_price" onchange="document.search.submit();">
<option value="">全部价格</option>
<option value="0-1000">0-1000元</option>
<option value="1000-3000">1000-3000元</option>
<option value="3000-5000">3000-5000元</option>
<option value="5000以上">5000元以上</option>
</select>
</div>
</form>
<!-- 筛选表单结束 -->
代码解释:
form的action指向list.php,这是织梦处理列表页的脚本。input type="hidden" name="tid":这是必须的,用于告诉系统当前是哪个栏目。select name="pf_brand":这里的name必须和第一步中我们定义的字段名完全一致。dede:sql标签:这是一个非常有用的标签,可以直接执行SQL,这里我们用它来从附加表dede_addonproduct中查询所有不为空的品牌,并生成下拉选项。~typeid~是一个占位符,在PHP中会被替换为当前栏目的ID。onchange="document.search.submit();":当用户选择一个选项后,表单会自动提交,实现即时筛选。
第四步:修改列表页PHP文件
这是核心的后端处理逻辑,我们需要修改 plus/list.php 文件,让它能识别我们自定义的筛选参数。
- 用FTP或文件管理器打开
/plus/list.php文件。 - 找到类似
if(!empty($keyword))的代码块,通常在if($typeid > 0)的附近。 - 在该位置添加以下PHP代码:
// ----------------- 自定义字段筛选 开始 -----------------
if (!empty($_GET['pf_brand'])) {
$pf_brand = addslashes($_GET['pf_brand']);
$addquery .= " AND (ctf.pf_brand = '$pf_brand')";
}
if (!empty($_GET['pf_price'])) {
$pf_price = addslashes($_GET['pf_price']);
$price_range = explode('-', $pf_price);
if (count($price_range) == 2) {
$min_price = intval($price_range[0]);
$max_price = intval($price_range[1]);
$addquery .= " AND (ctf.price >= $min_price AND ctf.price < $max_price)";
} elseif ($pf_price == '5000以上') {
$addquery .= " AND (ctf.price >= 5000)";
}
}
// ----------------- 自定义字段筛选 结束 -----------------
代码解释:
if (!empty($_GET['pf_brand'])):检查URL中是否存在pf_brand这个参数。$pf_brand = addslashes($_GET['pf_brand']);:获取参数并进行简单的安全处理。$addquery .= " AND (ctf.pf_brand = '$pf_brand')";:这是最关键的一步,它构建了一个SQL查询的附加条件,并将其追加到$addquery变量中。ctf是我们附加表dede_addonproduct的别名,pf_brand是字段名。- 价格区间处理:因为价格区间是 "min-max" 的格式,所以我们需要用
explode函数把它拆分成最小值和最大值,然后构建BETWEEN或>=、<这样的SQL条件。
注意:如果你的附加表不是 dede_addonproduct,或者你的字段名不是 pf_brand,请务必修改代码中的表名和字段名。

(图片来源网络,侵删)
第五步:修改列表页模板 (可选,但推荐)
为了让用户知道当前是按什么条件筛选的,最好在列表页显示当前的筛选条件。
在第三步的筛选表单中,可以添加一个“清除筛选”的链接,并显示当前选中的值。
修改筛选表单部分:
<!-- 筛选表单开始 -->
<form name="search" action="{dede:global.cfg_cmspath/}/plus/list.php" method="get">
<input type="hidden" name="tid" value="{dede:field name='id'/}" />
<!-- 品牌筛选 -->
<div>
<label for="pf_brand">品牌:</label>
<select name="pf_brand" id="pf_brand" onchange="document.search.submit();">
<option value="">全部品牌</option>
{dede:sql sql="SELECT distinct ctf.pf_brand FROM `dede_arctype` tp LEFT JOIN `dede_archives` a ON tp.id = a.typeid LEFT JOIN `dede_addonproduct` ctf ON a.id = ctf.id WHERE tp.reid = ~typeid~ AND ctf.pf_brand != ''"}
<option value="[field:pf_brand/]" {dede:var.name='pf_brand' function='IsSelect(@me)'} selected{/dede:var}>[field:pf_brand/]</option>
{dede:sql}
</select>
</div>
<!-- 价格筛选 -->
<div>
<label for="pf_price">价格区间:</label>
<select name="pf_price" id="pf_price" onchange="document.search.submit();">
<option value="">全部价格</option>
<option value="0-1000" {dede:var.name='pf_price' value='0-1000' function='IsSelect(@me)'} selected{/dede:var}>0-1000元</option>
<option value="1000-3000" {dede:var.name='pf_price' value='1000-3000' function='IsSelect(@me)'} selected{/dede:var}>1000-3000元</option>
<option value="3000-5000" {dede:var.name='pf_price' value='3000-5000' function='IsSelect(@me)'} selected{/dede:var}>3000-5000元</option>
<option value="5000以上" {dede:var.name='pf_price' value='5000以上' function='IsSelect(@me)'} selected{/dede:var}>5000元以上</option>
</select>
</div>
<!-- 显示当前筛选条件 -->
<div>
当前筛选:
{dede:global.pf_brand/}
{dede:global.pf_price/}
<a href="{dede:field name='phpurl'/}/list.php?tid={dede:field name='id'/}">清除筛选</a>
</div>
</form>
<!-- 筛选表单结束 -->
selected属性的判断逻辑需要你在list.php中将$_GET的值赋给全局变量,例如在list.php中添加global $pf_brand, $pf_price; $pf_brand = isset($_GET['pf_brand']) ? $_GET['pf_brand'] : '';。
总结与注意事项
- 字段名一致性:PHP中的
$_GET['xxx']、表单name="xxx"和数据库字段名xxx必须完全一致。 - 附加表:确保你的自定义字段在正确的附加表中(如
dede_addonarticle,dede_addonproduct等),并在list.php中使用正确的表别名(如cta,ctf)。 - SQL注入:
addslashes()是一个基本的安全措施,但对于生产环境,建议使用PDO或mysqli预处理语句来更安全地处理SQL。 - 分页问题:修改了
$addquery后,织梦的分页功能会自动适配,无需额外修改。 - 调试:如果筛选不生效,请检查浏览器地址栏提交的参数是否正确,并用
echo $addquery;在list.php中打印出最终的SQL语句,去数据库中手动执行看看是否有结果。
通过以上五个步骤,你就可以成功地在织梦CMS中实现功能强大的自定义字段筛选了。
