默认情况下,织梦的搜索页(search.php)是全局搜索,会遍历所有栏目和文档,但很多时候,我们希望用户可以在搜索前就选择一个或多个栏目进行定向搜索,就像很多网站的“在本栏目内搜索”功能一样。

这个功能的核心思路是:在搜索页添加一个包含所有栏目的下拉选择框,用户选择后,将选中的栏目ID(或多个ID)作为参数传递给search.php,然后在search.php中修改查询逻辑,使其只搜索选定的栏目。
下面是详细的实现步骤,分为前端改造和后端修改两部分。
第一步:前端改造 - 修改搜索表单 (search.php)
我们需要在搜索页的表单中增加一个栏目选择下拉框。
-
打开
search.php文件。
(图片来源网络,侵删) -
找到搜索表单,通常在文件的开头部分,类似这样:
<form name="formsearch" action="/search.php"> <input type="hidden" name="kwtype" value="0" /> <input type="text" name="q" size="12" /> <button type="submit">搜索</button> </form> -
在表单内部,
<input type="text">标签后面,添加一个<select>下拉菜单。<form name="formsearch" action="/search.php"> <input type="hidden" name="kwtype" value="0" /> <input type="text" name="q" size="12" placeholder="请输入关键词" /> <!-- 新增的栏目选择下拉框 --> <select name="typeid"> <option value="0">全站搜索</option> <!-- 这里将通过PHP动态生成所有栏目 --> {dede:channel type='son' currentstyle=''} <option value='[field:id/]'>[field:typename/]</option> {/dede:channel} </select> <button type="submit">搜索</button> </form>
代码解释:
<select name="typeid">: 我们给这个下拉框命名为typeid,这个typeid将作为参数传递给search.php。<option value="0">全站搜索</option>: 默认选项,值为0,代表不限制栏目(全站搜索)。{dede:channel type='son' currentstyle=''}: 这是织梦的栏目列表标签。type='son': 表示获取顶级栏目下的所有子栏目,如果你的网站栏目结构很深,你可能需要用type='self'来获取所有栏目(包括顶级和子级)。[field:id/]: 获取当前栏目的ID。[field:typename/]: 获取当前栏目的名称。
这样,前端就改造完成了,现在用户可以在搜索前选择一个栏目。

第二步:后端修改 - 修改搜索逻辑 (search.php)
这是最关键的一步,我们需要修改 search.php 文件,让它能够识别 typeid 这个参数,并据此修改SQL查询语句。
-
打开
search.php文件。 -
找到获取关键词和搜索类型的代码,通常在文件的开头部分,类似这样:
$q = trim($_GET['q']); $q = cn_substr($q, 30); // 限制关键词长度 $kwtype = isset($_GET['kwtype']) ? intval($_GET['kwtype']) : 0;
-
在它们后面,添加获取
typeid参数的代码:// ... 原有的 $q 和 $kwtype 代码 ... // 新增:获取用户选择的栏目ID $typeid = isset($_GET['typeid']) ? intval($_GET['typeid']) : 0;
-
找到生成SQL查询语句的核心代码,这部分代码通常在一个
if语句中,或者在查询数据库之前,寻找类似$query = "SELECT ... FROM dede_archives ..."的代码块。 -
修改SQL查询语句,加入对
typeid的判断。修改前(大概样子):
// ... 一些准备工作 ... $query = "SELECT arc.*,tp.typename,tp.corank,tp.isdefault,tp.typedir,tp.moresite,tp.siteurl,tp.sitepath FROM dede_archives arc LEFT JOIN dede_arctype tp ON arc.typeid=tp.id WHERE arc.arcrank > -1 $addsql ORDER BY arc.sortrank DESC LIMIT $startrow,$pagesize";修改后(加入
typeid判断):// ... 一些准备工作 ... // 初始化一个变量用于存放栏目ID的查询条件 $typeid_sql = ''; // 如果用户选择了栏目(typeid不为0),则添加栏目ID到查询条件中 if ($typeid > 0) { // 如果是单选,直接加上typeid $typeid_sql = " AND arc.typeid = '$typeid' "; // 如果是多选(需要修改前端表单为复选框或多选框),则使用 IN // 前端是 <select name="typeid[]" multiple> // $typeid_arr = isset($_GET['typeid']) ? $_GET['typeid'] : array(); // if (!empty($typeid_arr)) { // $typeid_str = implode(',', $typeid_arr); // $typeid_sql = " AND arc.typeid IN ($typeid_str) "; // } } // 将栏目条件拼接到最终的SQL语句中 $query = "SELECT arc.*,tp.typename,tp.corank,tp.isdefault,tp.typedir,tp.moresite,tp.siteurl,tp.sitepath FROM dede_archives arc LEFT JOIN dede_arctype tp ON arc.typeid=tp.id WHERE arc.arcrank > -1 $addsql $typeid_sql // 在这里加上 $typeid_sql ORDER BY arc.sortrank DESC LIMIT $startrow,$pagesize";
代码解释:
$typeid_sql = '';: 初始化一个空变量,用于存放SQL查询条件。if ($typeid > 0): 判断用户是否选择了栏目(typeid不为0)。$typeid_sql = " AND arc.typeid = '$typeid' ";: 如果选择了栏目,就生成一个AND arc.typeid = '选中的ID'的条件,这个条件会被拼接到主查询语句中,从而实现按栏目筛选。... $addsql $typeid_sql ...: 将我们新构建的栏目条件$typeid_sql拼接到原有的SQL查询条件$addsql后面。
第三步:增强功能 - 在搜索结果页显示当前搜索的栏目
为了让用户知道他当前是在哪个栏目下搜索的,我们可以在搜索结果页的标题或面包屑中显示出来。
-
打开搜索结果页模板文件:
templets/default/search.htm。 -
在页面的标题或面包屑位置,添加以下代码:
<h2>搜索结果</h2> <!-- 新增:显示当前搜索的栏目 --> {if $typeid > 0} <p class="search-tips">您正在栏目 <strong>{dede:field name='typename'/}</strong> 中搜索</p> {/if} <!-- 原有的面包屑也可以修改 --> <div class="position"> <a href='{dede:global.cfg_cmsurl/}/'>首页</a> {if $typeid > 0} » <a href='{dede:field name='typeurl'/}'>{dede:field name='typename'/}</a> {/if} » 搜索结果 </div>
代码解释:
{if $typeid > 0}: 模板引擎会判断PHP传递过来的$typeid变量是否大于0。{dede:field name='typename'/}: 这个标签只有在指定了typeid的情况下才能正常工作,它会显示当前栏目的名称。{dede:field name='typeurl'/}: 同样,显示当前栏目的链接。
这样,当用户选择“新闻”栏目进行搜索时,页面就会显示“您正在栏目 新闻 中搜索”,并且面包屑也会正确指向“新闻”栏目。
总结与注意事项
-
功能流程:
- 用户在
search.php看到带栏目下拉框的搜索表单。 - 用户输入关键词,选择“新闻”栏目,点击搜索。
- 浏览器向
search.php?q=关键词&typeid=新闻的ID发送请求。 search.php接收到请求,获取到typeid。search.php修改SQL,只查询typeid为“新闻的ID”的文档。search.php将结果和$typeid变量一起传递给模板search.htm。search.htm渲染页面,并显示“您正在栏目 新闻 中搜索”。
- 用户在
-
多选功能:如果你希望支持多栏目搜索,需要将前端的
<select name="typeid">改为<select name="typeid[]" multiple>,并在后端使用implode和IN语句来处理多个ID。 -
缓存问题:修改
search.php后,如果搜索结果没有变化,请检查是否开启了模板缓存,并尝试刷新缓存。 -
兼容性:此方法适用于织梦DedeCMS 5.7及更高版本,核心逻辑在旧版本中也基本通用,但文件路径和标签可能略有差异。
通过以上三步,你就成功地为织梦搜索页添加了对特定栏目(dede:type)的支持,大大提升了用户体验和搜索的精准度。
