这个功能非常实用,可以让用户根据多个维度(如关键词、栏目、发布时间、作者等)来筛选内容,极大地提升用户体验。
我们将以最常见的场景为例:一个包含“关键词搜索”、“栏目选择”和“发布时间范围”的搜索表单。
实现步骤
整个实现过程分为三个核心部分:
- 前端模板:创建用户输入搜索条件的表单。
- 后端处理:修改织梦的核心文件,接收并处理搜索请求。
- 结果页模板:展示搜索结果的页面。
第一步:创建搜索表单模板
在你的网站模板目录(通常是 /templets/default/)下,创建一个搜索页面,search.htm。
这个页面将包含一个表单,用户可以在其中输入多个条件。
/templets/default/search.htm 示例代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">多条件搜索</title>
</head>
<body>
<h1>内容搜索</h1>
<form name="search" action="{dede:global.cfg_cmspath/}/plus/search.php" method="get">
<!-- 1. 关键词搜索 -->
<div>
<label for="keyword">关键词:</label>
<input type="text" name="keyword" id="keyword" placeholder="请输入搜索关键词">
</div>
<!-- 2. 栏目选择 -->
<div>
<label for="typeid">栏目:</label>
{dede:channel type='son' current='0'}
<input type="checkbox" name="typeid[]" id="typeid_{dede:field.id/}" value="{dede:field.id/}">
<label for="typeid_{dede:field.id/}">{dede:field.typename/}</label>
{/dede:channel}
<!-- 如果需要下拉选择,可以使用下面的代码 -->
<!-- <select name="typeid">
<option value="0">所有栏目</option>
{dede:channel type='son' current='0'}
<option value="{dede:field.id/}">{dede:field.typename/}</option>
{/dede:channel}
</select> -->
</div>
<!-- 3. 发布时间范围 -->
<div>
<label for="starttime">发布时间:</label>
从 <input type="date" name="starttime" id="starttime">
至 <input type="date" name="endtime" id="endtime">
</div>
<!-- 4. 提交按钮 -->
<div>
<button type="submit">搜索</button>
</div>
</form>
</body>
</html>
代码解析:
action="{dede:global.cfg_cmspath/}/plus/search.php":这是织梦处理搜索的核心文件,表单数据会提交到这里。name="keyword":标准的织梦关键词搜索参数。name="typeid[]":注意,这里使用了[],表示我们可以同时选择多个栏目,这会向search.php传递一个数组。name="starttime"和name="endtime":我们自定义的参数,用于接收日期范围。
第二步:修改后端处理文件 search.php
这是实现多条件搜索的核心,我们需要修改 /plus/search.php 文件,让它能够识别我们新增的 typeid[]、starttime 和 endtime 参数,并将其整合到SQL查询语句中。
/plus/search.php 修改步骤:
-
找到构建SQL查询的核心代码:在
search.php文件中,找到类似$typeid = (empty($typeid) || is_numeric($typeid)) ? $typeid : 0;的地方,以及构建$query变量的代码段。 -
增加条件判断:在构建
$query之前,加入对我们新增参数的处理。
修改后的 /plus/search.php 关键代码示例:
<?php
require_once(dirname(__FILE__)."/../include/common.inc.php");
// --- 新增代码开始 ---
// 接收并处理自定义参数
$addtype = isset($addtype) ? $addtype : '';
$starttime = isset($starttime) && $starttime ? GetMkTime($starttime) : 0; // 将日期转换为时间戳
$endtime = isset($endtime) && $endtime ? GetMkTime($endtime) : 0;
// 处理typeid数组,如果是多选,需要转换成IN语句的格式
if (!empty($typeid) && is_array($typeid)) {
$typeid_str = implode(',', array_filter($typeid, 'is_numeric')); // 过滤非数字ID并拼接成字符串
if (empty($typeid_str)) {
$typeid_str = '0'; // 如果没有选择有效栏目,默认为0
}
} else {
$typeid = (empty($typeid) || !is_numeric($typeid)) ? 0 : $typeid;
$typeid_str = $typeid;
}
// --- 新增代码结束 ---
// 获取搜索关键字
$keyword = empty($keyword) ? '' : trim(FilterSearch($keyword));
// 设置搜索结果排序
$orderby = empty($orderby) ? 'default' : strtolower($orderby);
$uppage = $uppage == '' ? 0 : 1;
$channeltype = empty($channeltype) ? 0 : intval($channeltype);
$mid = empty($mid) ? 0 : intval($mid);
// 获取搜索模板
$tempfile = empty($tempfile) ? '' : trim($tempfile);
if($tempfile=='') {
$tempfile = SearchGetTemplet($typeid);
}
// 获取分页
$List = new SearchView($typeid, $channeltype, $mid, $keyword, $orderby, $tempfile, $getarcrank);
$List->PageSize = empty($pagesize) ? 10 : intval($pagesize);
$List->TypeLink = $tp;
// --- 修改SQL查询构建部分 ---
// 原始代码可能是 $query = "SELECT arc.*,tp.typedir,tp.typename,tp.corank,tp.isdefault,tp.defaultname,tp.namerule,
// tp.namerule2,tp.ispart,tp.moresite,tp.siteurl,tp.sitepath FROM `dede_archives` arc LEFT JOIN `dede_arctype` tp ON arc.typeid=tp.id WHERE 1=1 ";
// 我们需要修改这个WHERE子句
// 构建WHERE条件
$where = " WHERE 1=1 ";
// 1. 关键词条件
if (!empty($keyword)) {
$where .= " AND (arc.title LIKE '%$keyword%' OR arc.keywords LIKE '%$keyword%' OR arc.description LIKE '%$keyword%') ";
}
// 2. 栏目条件 (如果typeid_str不为0)
if ($typeid_str != '0') {
$where .= " AND arc.typeid IN ($typeid_str) ";
}
// 3. 发布时间范围条件
if ($starttime > 0) {
$where .= " AND arc.senddate >= $starttime ";
}
if ($endtime > 0) {
// 注意:结束日期应该是这一天的最后一秒,所以加 86400 (24*60*60)
$where .= " AND arc.senddate <= " . ($endtime + 86400);
}
// 4. 其他条件,如会员权限等
$addsql = '';
if ($channeltype > 0) $addsql .= " And arc.channeltype = '$channeltype' ";
if ($addsql!='') $where .= $addsql;
if ($arcrank!='') $where .= " And arc.arcrank = '$arcrank' ";
if ($mid > 0) $where .= " And arc.mid = '$mid' ";
// 最终组合完整的查询语句
$query = "SELECT arc.*,tp.typedir,tp.typename,tp.corank,tp.isdefault,tp.defaultname,tp.namerule,tp.namerule2,tp.ispart,tp.moresite,tp.siteurl,tp.sitepath
FROM `dede_archives` arc
LEFT JOIN `dede_arctype` tp ON arc.typeid=tp.id
{$where}
ORDER BY arc.sortrank DESC";
// --- 修改结束 ---
// ... 后续的分页和模板渲染代码基本保持不变 ...
// $sql = preg_replace("/SELECT(.*?)FROM/is", "SELECT COUNT(*) AS dd FROM ", $query);
// $row = $dsql->GetOne($sql);
// $totalresult = $row['dd'];
// ... 等等 ...
代码解析:
- 参数接收:我们获取了
starttime和endtime,并使用GetMkTime()将它们从日期字符串(如 "2025-10-01")转换为Unix时间戳,这是数据库中senddate字段的格式。 typeid处理:这是最关键的一步,因为表单传递的是typeid[]数组,我们需要用implode()将它转换成1,3,5这样的字符串,以便用在IN子句中。WHERE子句构建:我们通过if语句判断每个参数是否存在,然后动态地拼接WHERE条件,这样,只有用户填写了某个条件,才会将其加入SQL查询,保证了查询的灵活性。- 安全性:
FilterSearch()函数对关键词进行了过滤,防止SQL注入。is_numeric()和array_filter()确保了typeid的安全性。
第三步:创建搜索结果页模板
搜索结果页通常使用默认的 search.htm 模板,或者你可以通过 tempurl 参数指定一个专门的模板,为了更好的控制,我们创建一个专门的模板 search_list.htm。
/templets/default/search_list.htm 示例代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">搜索结果 - {dede:global.keyword/}</title>
</head>
<body>
<h1>搜索结果</h1>
<p>您搜索的关键词是:<strong>{dede:global.keyword/}</strong></p>
<!-- 如果有结果 -->
{dede:list pagesize='10'}
<div class="result-item">
<h2><a href="[field:arcurl/]">[field:title/]</a></h2>
<p class="info">栏目:[field:typename/] | 发布时间:[field:pubdate function="MyDate('Y-m-d',@me)"] | 作者:[field:writer/]</p>
<p class="summary">[field:description function="cn_substr(@me, 200)"]...</p>
</div>
{/dede:list}
<!-- 如果没有结果 -->
{dede:if empty='list'}
<p>抱歉,没有找到与 "<strong>{dede:global.keyword/}</strong>" 相关的内容。</p>
{/dede:if}
<!-- 分页 -->
<div class="page">
{dede:pagelist listsize='5' listitem='info,index,end,pre,next,pageno'}
{/dede:pagelist}
</div>
</body>
</html>
如何使用这个模板?
在你的 search.htm 表单中,可以指定结果页模板:
<form ...>
...
<input type="hidden" name="tempurl" value="/templets/default/search_list.htm">
<button type="submit">搜索</button>
</form>
总结与注意事项
- 备份:在修改
search.php之前,务必备份原文件! - 调试:如果功能不正常,可以尝试在
search.php中echo $query; exit;来打印最终的SQL语句,检查它是否符合你的预期。 - 扩展性:这个方法可以轻松扩展,如果你想增加“按作者搜索”,只需在表单中添加一个
<input name="author">,然后在search.php中增加一个if (!empty($author)) { $where .= " AND arc.writer = '$author' "; }条件即可。 - 性能:多条件搜索,特别是范围搜索,可能会对数据库造成一定压力,确保你的
dede_archives表的typeid和senddate字段有建立索引。 - URL重写:如果你的网站开启了URL静态化,搜索结果的链接也会自动变成静态格式,这通常由织梦自动处理,无需额外配置。
通过以上三步,你就成功地为织梦CMS实现了一个功能完善、用户体验良好的多条件搜索功能。
