织梦DedeCMS手机搜索跳转PC站搜索的修复方法与排查思路

织梦dedecms手机端搜索框点击后跳转到PC站搜索页面,体验极差?本文给出两种修复方案,重点推荐修改plus/search.php添加mobile参数判断的简易方法,让手机用户搜索后正确显示WAP搜索结果页。

张文保 更新 13 分钟阅读 2,631 阅读

保哥从 2012 年开始接手第一个 DedeCMS 项目,到 2017 年那波移动化改造高峰期,一共维护过 40 多个基于织梦 5.7 的网站,其中绝大部分都遇到过同一个问题:PC 端用 default 模板,手机端用 default_m 模板,但访问者在手机上点搜索按钮,结果直接跳到了 PC 站的搜索结果页。这种情况下不仅 UA 体验很差,搜索框、列表样式全部错位,移动端跳出率会瞬间拉高。

这篇文章我会把当年踩过的所有坑、两种修复方案的代码细节、以及怎么验证修复效果一次性说清楚。如果你正在维护一个还没退役的织梦站,或者在做老站迁移前的应急修补,可以照着流程走一遍。

一、问题的根本原因:DEDEMOB 常量没有被正确赋值

织梦 DedeCMS 在 /include/arc.searchview.class.php 文件里通过判断常量 DEDEMOB 来决定加载哪一套模板。DEDEMOB 等于 Y 时使用 search_m.htm(移动端模板),否则使用 search.htm(PC 端模板)。

问题在于,/plus/search.php 这个入口文件并没有把当前请求的设备类型透传给 arc.searchview.class.php。也就是说,手机用户提交搜索表单后,PHP 端无法知道这是来自手机端的请求,于是默认走 PC 流程。

保哥当年第一次排查时,绕了不少弯路:先是怀疑是 .htaccess 的跳转规则误伤了 /plus/search.php,又怀疑是 CDN 在 PC/Mobile 分流时忽略了 ?keyword=... 这种带参数的请求。最后用 var_dump 打印 define 结果才确认 —— 是织梦自身的 PHP 流程缺少了一个变量传递。

// /include/arc.searchview.class.php 大概在 60-70 行
if (defined('DEDEMOB')) {
    $this->Templet = $cfg_basedir.$cfg_templets_dir.'/'.$cfg_df_style.'/search_m.htm';
} else {
    $this->Templet = $cfg_basedir.$cfg_templets_dir.'/'.$cfg_df_style.'/search.htm';
}

知道根本原因后,修复思路就很清晰:/plus/search.php 在判定为手机请求时,主动定义 DEDEMOB

二、修复方案一:通过隐藏字段传递 mobile 标识

这是保哥推荐的方案,改动小、回滚也简单。整个流程分三步。

第一步:修改 /plus/search.php

打开 /plus/search.php,搜索下面这行代码(大约在第 18 至 22 行之间,不同版本行号略有差异):

$mid = (isset($mid) && is_numeric($mid)) ? $mid : 0;

在它的下方追加:

$mobile = (isset($mobile) && is_numeric($mobile)) ? $mobile : 0;
if ($mobile == 1) {
    define('DEDEMOB', 'Y');
}

这段代码的逻辑很简单:从 $_REQUEST 拿到 mobile 参数,如果它等于 1,就告诉后续的 arc.searchview.class.php,当前请求要用手机端模板。

第二步:在手机模板的搜索表单里加隐藏 input

打开 /templets/default_m/head.htm(或者你的手机模板对应的搜索框所在文件),找到 <form action="/plus/search.php"> 这一段,在 </form> 之前加上:

<input type="hidden" name="mobile" value="1" />

这样手机端任何一次搜索请求,都会带上 mobile=1,PHP 端就能识别。

第三步:清空缓存并测试

保哥当年最常踩的坑就是改完代码忘了清缓存:

  • 进入后台 → 系统 → 系统基本参数 → 更新缓存
  • 用浏览器隐私模式访问手机站,确认 Set-Cookie 没有把旧的 PC 跳转记下来
  • 用 Chrome DevTools 的 Device Mode 切到 iPhone 12 Pro,提交搜索关键词,看返回的 HTML 头部是否引用了 default_m 的 CSS

三、修复方案二:复制一份手机专用搜索文件

如果第一种方案因为模板权限或者甲方不允许改 /plus/search.php,可以走方案二,思路是 复制隔离

# 在服务器上备份并复制
cp /plus/search.php /plus/wapsearch.php
cp /include/arc.searchview.class.php /include/arc.wapsearchview.class.php

然后改三个地方:

  1. /plus/wapsearch.php 顶部把 require_once 的目标从 arc.searchview.class.php 改成 arc.wapsearchview.class.php
  2. wapsearch.php 里强制 define('DEDEMOB', 'Y');
  3. /include/arc.wapsearchview.class.php 中把默认模板路径硬写成 search_m.htm

手机端模板的搜索表单 action 改成 /plus/wapsearch.php,PC 端继续用 /plus/search.php,两条路径完全隔离。

这个方案的优点是改动只限于手机端,PC 端的逻辑文件一行都不动;缺点是以后官方升级、或者你想给搜索加防刷限流时,要同时维护两份代码。保哥更倾向于方案一,除非你接手的是一个完全不允许碰核心文件的项目。

四、配套要做的三件事:跳转、安全、监测

仅仅修好搜索页的模板加载,还不够。当年保哥交付一个客户站时,专门列了三项配套清单。

4.1 PC 与手机的双向跳转

.htaccess 里加 UA 判断,让 PC 用户访问 /m/ 子目录时反向回到 PC 站,反之亦然。否则你的搜索改完,但首页跳转还是错的,整体体验依旧别扭。

RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (iPhone|Android|Mobile) [NC]
RewriteCond %{REQUEST_URI} !^/m/
RewriteRule ^(.*)$ /m/$1 [L,R=302]

4.2 防止 search.php 被刷

搜索接口最容易被薅,保哥处理过的站点里有一个三天里被刷了 80 万次 /plus/search.php?keyword=xxx,把数据库 CPU 打到 100%。在改完模板逻辑后,建议同时加一段速率限制:

// /plus/search.php 顶部
$ip = $_SERVER['REMOTE_ADDR'];
$cacheKey = 'search_rate_' . md5($ip);
if (file_exists(DEDEDATA . '/' . $cacheKey)) {
    $last = (int)file_get_contents(DEDEDATA . '/' . $cacheKey);
    if (time() - $last < 2) {
        die('请求过于频繁');
    }
}
file_put_contents(DEDEDATA . '/' . $cacheKey, time());

两秒一次的频率,基本能挡住绝大多数自动化脚本,又不影响真实用户。

4.3 用日志验证修复是否真正生效

保哥习惯在 /include/arc.searchview.class.php 顶部临时加一行日志,跑两天后再撤掉:

file_put_contents(
    DEDEDATA . '/search_debug.log',
    date('Y-m-d H:i:s') . ' UA=' . $_SERVER['HTTP_USER_AGENT'] . ' DEDEMOB=' . (defined('DEDEMOB') ? 'Y' : 'N') . PHP_EOL,
    FILE_APPEND
);

两天后打开 search_debug.log,看手机端 UA 的请求是不是 100% 都标了 DEDEMOB=Y。如果中间出现 N,就说明还有遗漏的入口(比如某个旧主题里的搜索框没加隐藏 input)。

五、迁移建议:织梦已停止维护,搜索修复只是缓兵之计

2018 年织梦官方停止商业授权和安全更新后,保哥就开始劝甲方迁移。手机搜索跳转这个 Bug 即使修好,DedeCMS 还有一长串遗留问题:会员模块的 SQL 注入、tag.php 的 XSS、/plus/recommend.php 的 GETSHELL,都是公开漏洞。

如果你正在做内容站迁移,可以参考保哥之前整理的几条路径:

  • 内容量小(< 1000 篇):直接迁到 Typecho,写个简单的 Python 脚本读 dede_archives 转成 Markdown 即可
  • 内容量中(1000–10000 篇):迁到 WordPress,社区有比较成熟的 dede2wp 插件
  • 内容量大或带商城:迁到 Drupal 或者直接做 Headless(Strapi + Next.js)

搜索页修复后,先稳住流量,再用 6 到 12 个月做平稳迁移,是更现实的路线。

六、FAQ:保哥的实战问答

Q1:我修改完 /plus/search.php 后,手机搜索还是跳到 PC,可能是什么原因?

按出现频率从高到低排查:① 模板的搜索 form 里没加 <input type="hidden" name="mobile" value="1" />;② 后台缓存没清;③ CDN 把 search.php 的 HTML 缓存了,去 CDN 后台手动刷新这个 URL;④ 你的手机模板用的是 GET 提交但 form 没写 method,少数浏览器会丢参数。

Q2:能不能不通过隐藏字段,而是直接用 PHP 检测 UA 来判断?

可以。把 /plus/search.php 里那段判断改成 if (preg_match('/iPhone|Android|Mobile/i', $_SERVER['HTTP_USER_AGENT'])) define('DEDEMOB','Y'); 即可。但保哥不推荐这种做法,因为 UA 误判率比较高,平板、爬虫、PC 浏览器开 DevTools 模拟移动端时,都会被错误识别。隐藏字段的方式更稳。

Q3:改完后 SEO 会不会受影响?

不会。手机搜索结果页本来就不应该被搜索引擎收录(带 ?keyword= 的页面通常 robots 已 disallow)。如果你担心,就在 <head> 里加 <meta name="robots" content="noindex,follow">,让搜索引擎不收录但仍然跟踪外链。

Q4:织梦官方有没有正式补丁?

截至 2025 年,织梦官方早已停止常规更新,这个手机搜索跳转的 Bug 在 5.7 SP2 UTF-8 版本里依然存在,没有官方补丁。你看到的所有“DedeCMS 移动端搜索修复”都是社区自发整理,包括本文的两种方案。

写在最后

手机搜索跳 PC 这个问题看起来小,但它是一个典型的“CMS 默认行为与终端检测脱节”的案例。保哥从 2017 年那次大改造之后,每次接手老站第一件事就是测搜索 + 测分页 + 测翻页 RSS,三处都跑通才算修复完成。希望这篇文章能帮你少踩一些坑,也欢迎在留言区告诉保哥你那边的特殊场景。

分享到
标签
版权声明

本文标题:《织梦DedeCMS手机搜索跳转PC站搜索的修复方法与排查思路》

本文链接:https://zhangwenbao.com/methods-dedecms-own-mobile-phone-terminal-dedecms-web-search-page-to-jump-directly-to-the-searchmhtm-mobile-phone-station-page.html

版权声明:本文原创,转载请注明出处和链接。许可协议: CC BY-NC-SA 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交