search.php 是织梦CMS的核心搜索功能文件,它负责接收用户的搜索请求、处理关键词、调用数据库、并最终展示搜索结果,理解这个文件对于自定义搜索功能、修改搜索逻辑或解决搜索问题至关重要。
search.php 的核心功能和工作流程
当用户在前台执行搜索时(点击一个带有 action="/search.php" 的表单),search.php 就会启动,其基本流程如下:
- 接收请求:获取用户通过GET或POST方式提交的搜索关键词 (
keyword)。 - 初始化环境:加载必要的织梦核心文件,初始化数据库连接、全局变量等。
- 安全处理:对搜索关键词进行过滤,防止SQL注入和XSS攻击。
- 获取分页参数:获取当前是第几页 (
pageno) 和每页显示多少条结果 (pagesize)。 - 调用搜索逻辑:这是最核心的一步,根据配置调用不同的搜索方法(默认是全文索引搜索)。
- 查询数据库:执行SQL查询,从主表 (
dede_archives) 或全文索引表中获取匹配的文章ID列表。 - 获取结果详情:根据上一步得到的ID列表,批量查询文章的详细信息(标题、发布时间等)。
- 高亮关键词:将文章标题和内容中的搜索关键词用特定样式(如
<font color="red">)高亮显示。 - 处理分页:计算总页数,生成分页链接。
- 加载模板:加载
search.htm模板文件。 - 输出结果:将处理好的数据(关键词、结果列表、分页信息等)赋值给模板变量,并最终渲染输出给用户。
search.php 文件结构详解
下面是一个典型的 search.php 文件代码结构,并附有详细注释。
<?php
/**
* 织梦搜索文件
*
* @version $Id: search.php 1 15:21 2010年7月12日Z tianya $
* @package DedeCMS.Site
* @copyright Copyright (c) 2007 - 2010, DesDev, Inc.
* @license http://help.dedecms.com/usersguide/license.html
* @link http://www.dedecms.com
*/
// 引入公共底层文件,这是织梦CMS的入口文件
require_once (dirname(__FILE__) . "/include/common.inc.php");
// 引入搜索相关的函数库
require_once DEDEINC."/search.class.php";
// --- 1. 获取并处理搜索关键词 ---
$keyword = empty($keyword) ? '' : trim($keyword);
$keyword = FilterSearch($keyword); // 调用内置函数进行安全过滤
// --- 2. 初始化搜索类 ---
// 实例化搜索类,传入关键词和每页显示数量
// $pagesize 通常在后台“核心设置”中配置,默认为10
$search = new Search($keyword, $pagesize);
// --- 3. 获取分页信息 ---
// 获取当前页码,默认为第1页
$pageno = isset($pageno) && is_numeric($pageno) ? intval($pageno) : 1;
// --- 4. 执行搜索查询 ---
// 调用GetResult()方法执行搜索,返回匹配的记录总数
$totalResult = $search->GetResult($pageno);
// 如果没有搜索结果,则直接输出并结束
if ($totalResult == 0)
{
$dlist = new DataList();
$dlist->SetTemplate($cfg_basedir . $cfg_templets_dir . "/search.htm");
$dlist->Display();
exit();
}
// --- 5. 获取并处理搜索结果列表 ---
// 获取当前页的结果数据
$list = $search->GetArcList();
// --- 6. 准备模板变量 ---
// 将搜索关键词和结果总数传递给模板
$oldkeyword = $keyword;
$keyword = htmlspecialchars($keyword); // 再次对关键词进行HTML实体转义,用于安全显示
$TypeLink = new TypeLink($typeid);
$typename = $TypeLink->GetTypeName();
// 获取分页链接
$plist = $search->GetPageList($list);
// 将所有变量放入一个数组中,方便模板调用
$addfields = array();
foreach($list as $k=>$v)
{
// 可以在这里处理附加字段,如文章图片等
$addfields[$k] = $v;
}
// --- 7. 加载并渲染模板 ---
$dlist = new DataList();
$dlist->SetTemplet($cfg_basedir . $cfg_templets_dir . "/search.htm"); // 指定搜索结果模板
$dlist->SetSource($list); // 设置数据源
$dlist->Display(); // 渲染并输出模板
?>
关键类和函数解析
-
FilterSearch($keyword)- 位置:
include/filter.inc.php - 功能:对用户输入的搜索关键词进行过滤,移除一些可能导致安全问题的字符和词语,这是防止SQL注入和XSS攻击的第一道防线。
- 位置:
-
new Search($keyword, $pagesize)- 位置:
include/search.class.php - 功能:实例化搜索核心类,这个类封装了所有搜索相关的逻辑。
$keyword: 搜索关键词。$pagesize: 每页显示结果数,通常从全局配置$cfg_search_pagesize中获取。
- 位置:
-
$search->GetResult($pageno)- 功能:执行搜索查询,并返回匹配的总记录数,这个方法会根据后台设置(是否开启全文索引)来决定是走全文索引还是
LIKE查询。 - 全文索引:效率极高,适合数据量大的网站,查询
dede_searchindex表。 - LIKE查询:效率较低,适合数据量小的网站或全文索引未开启时,直接查询
dede_archives表的title和description字段。
- 功能:执行搜索查询,并返回匹配的总记录数,这个方法会根据后台设置(是否开启全文索引)来决定是走全文索引还是
-
$search->GetArcList()- 功能:在
GetResult()找到文章ID后,这个方法会根据ID列表批量查询dede_archives表,获取文章的详细信息(标题、作者、发布时间、栏目ID等)并返回一个结果数组。
- 功能:在
-
$search->GetPageList($list)- 功能:根据总记录数和每页显示数量,生成分页链接字符串(如
上一页 1 2 3 4 5 下一页)。
- 功能:根据总记录数和每页显示数量,生成分页链接字符串(如
-
new DataList()- 功能:织梦的数据列表渲染类,它负责将PHP数据变量传递给HTML模板,并最终合并输出。
如何自定义搜索功能?
修改搜索结果模板
这是最常见的自定义需求,你只需要修改 templets/default/search.htm 文件。
search.htm 常用模板变量:
{dede:global name='keyword' function='RemoveXSS(@me)'/}: 安全显示搜索关键词。{dede:global name='result'/}: 显示搜索结果总数,如“找到 15 条结果”。{dede:list pagesize='10'}: 循环输出搜索结果列表。[field:title/]: 文章标题(关键词已高亮)。[field:arcurl/]: 文章链接。[field:pubdate function="MyDate('Y-m-d',@me)"/]: 发布日期。[field:description/]: 关键词已高亮)。[field:typeid/]: 栏目ID。[field:typename/]: 栏目名称。
{dede:pagelist listsize='4' listitem='info,index,end,pre,next,pageno'/}: 调用分页条。
修改搜索逻辑(进阶)
如果你需要修改搜索的匹配规则(只搜索特定栏目、搜索附加字段等),你需要修改 include/search.class.php 文件。
只搜索指定栏目(ID为1和2)的文章
在 search.class.php 的 GetKeywordList() 方法中,找到生成SQL查询的部分,在 WHERE 条件中增加栏目ID的限制。
// 原始代码可能类似
// $query = "SELECT aid FROM `{$this->AddTable}` WHERE {$this->GetCondition()}";
// 修改后
$addQuery = " AND typeid IN (1, 2)"; // 增加栏目ID限制
$query = "SELECT aid FROM `{$this->AddTable}` WHERE {$this->GetCondition()} $addQuery";
警告:直接修改核心文件可能会导致升级困难,建议做好备份或在二次开发时进行。
修改搜索表单
搜索的表单通常位于网站的页头 (header.htm) 或其他公共模板中,确保你的搜索表单 action 属性指向 search.php,并且输入框的 name 属性为 keyword。
<form name="formsearch" action="/search.php">
<input type="hidden" name="kwtype" value="0" />
<input type="hidden" name="searchtype" value="titlekeyword" />
<input name="keyword" type="text" class="search-keyword" />
<button type="submit" class="search-submit">搜索</button>
</form>
kwtype: 0表示关键词搜索,1表示使用AND逻辑,2表示使用OR逻辑。searchtype:titlekeyword表示在标题和关键词中搜索,title表示只在标题中搜索。
五. 常见问题与解决方案
-
搜索结果为空,但确定有相关文章
- 原因:最常见的原因是全文索引未更新或损坏。
- 解决方案:
- 登录织梦后台 -> 系统 -> 系统设置 -> SQL命令行工具。
- 在命令行中执行以下命令,重建全文索引:
ALTER TABLE `dede_archives` ADD FULLTEXT(`title`,`description`);
- 或者,在后台的“内容发布”或“搜索设置”里找到重建索引的选项。
-
搜索效率非常慢
- 原因:网站数据量过大,且未开启全文索引,导致使用
LIKE查询,全表扫描非常耗时。 - 解决方案:按照上述方法,为
title和description字段添加全文索引。
- 原因:网站数据量过大,且未开启全文索引,导致使用
-
想搜索文章内容(body)
- 原因:默认搜索不包含文章正文内容,因为全文索引默认不包含
body字段(该字段非常大,会严重影响索引效率)。 - 解决方案:
- 高风险方案:为
body字段添加全文索引(ALTER TABLE ... ADD FULLTEXT(body)),这会极大消耗服务器资源和拖慢更新速度,不推荐大网站使用。 - 推荐方案:使用第三方搜索插件,如基于Elasticsearch或Sphinx的搜索方案,它们专门为海量数据搜索优化。
- 高风险方案:为
- 原因:默认搜索不包含文章正文内容,因为全文索引默认不包含
希望这份详细的解析能帮助你完全理解织梦的 search.php 文件!
