DedeCMS 报 ereg_replace deprecated 的根因与修复

把织梦搬到PHP5.3或更高版本就报“Function ereg_replace() is deprecated”?这是因为ereg_replace已被废弃。本文针对Linux和Windows两种环境分别给出/dede/config.php的精确替换代码,几行改动即可让DedeCMS兼容新版PHP。

张文保 更新 9 分钟阅读 3,153 阅读

我和这个报错的渊源

我是保哥。我接触织梦 DedeCMS 是在 2013 年前后,那时候做企业站、地方门户站,DedeCMS 几乎是国内 PHP CMS 里的首选。它模板简单、生成静态、SEO 友好,缺点也很明显——更新慢、代码老、对新版 PHP 兼容性差。

2017 年前后,国内主机商开始大规模把默认 PHP 版本从 5.2 / 5.3 升级到 5.6 甚至 7.x。很多老站长一觉醒来,网站后台直接打不开,浏览器里赫然写着一行:

Deprecated: Function ereg_replace() is deprecated in /home/wwwroot/your-site/dede/config.php on line XX

严重一点的,前台都打不开,整个网站白屏。当时我每周接到的求助里,至少有三分之一是因为这个报错。本文把我当时整理给客户的解决方案重新梳理一遍,包含根因、Linux/Windows 两套修复办法、以及若干我后来补充的工程化建议。

错误的根本原因:PHP 5.3 起废弃了 POSIX 正则函数

要解决问题,先得明白它是怎么来的。ereg_replace() 属于 PHP 早期的 POSIX 风格正则扩展(ext/ereg),从 PHP 5.3.0 开始被官方标记为「Deprecated(已废弃)」,到 PHP 7.0 直接被移除。

替代它的是 PCRE 风格的 preg_replace(),速度更快、语法更现代,是目前 PHP 唯一推荐的正则方案。

DedeCMS 由于多年没有大版本更新,源码里依旧大量保留着 ereg_replace()split()eregi() 等旧函数。一旦把这套老代码扔到 PHP 5.3 以上的主机环境,PHP 解释器就会持续抛出 Deprecated 警告。如果你的 php.inidisplay_errors = Onerror_reporting 包含 E_DEPRECATED,这些警告就会直接打印到页面上,看起来就像「网站坏了」。

值得强调一句:这不是织梦源码本身被改坏了,也不是空间商在搞鬼,而是 PHP 语言本身的演进让老代码不兼容了。

Linux 主机的修复方法

绝大多数的 DedeCMS 站点跑在 Linux 服务器上(CentOS / Ubuntu / Debian + Nginx 或 Apache)。修复步骤如下。

第一步,用 SFTP 或者 SSH 进入服务器,定位到网站根目录下的 dede/config.php 文件。注意 dede 这个目录名很多老站长出于安全考虑改过,比如改成了 admin8848,需要按你自己的情况找对路径。

第二步,用编辑器打开该文件,定位到这一行:

define('DEDEADMIN', ereg_replace("[/\\]{1,}", '/', dirname(__FILE__) ) );

第三步,把它替换成 PCRE 写法:

define('DEDEADMIN', preg_replace("/[\/\\\\]{1,}/", '/', dirname(__FILE__) ) );

这里有几个细节我必须强调,因为我当年帮人改的时候踩过坑:

  • preg_replace 的正则需要使用定界符(这里我用 /),而 ereg_replace 不需要。
  • 反斜杠在 PHP 字符串里要写两层,在正则里再要一层转义,所以最终是四个反斜杠 \\\\,看起来吓人但是必须的。
  • 替换后保存,建议直接用 UTF-8 无 BOM 编码,避免中文目录路径出问题。

第四步,刷新网站,Deprecated 报错应该立刻消失。

Windows 主机的修复方法

少数站长用的是 Windows + IIS 主机,路径分隔符是反斜杠 \。这种环境下用 preg_replace 处理路径反而绕弯,更简洁的方案是直接用 strtr

找到同样这一行:

define('DEDEADMIN', ereg_replace("[/\\]{1,}", '/', dirname(__FILE__) ) );

替换成:

define('DEDEADMIN', strtr(dirname(__FILE__), '\\/', '//'));

strtr 的作用是把第一个参数里出现的反斜杠和正斜杠统一替换成正斜杠,效率比 preg_replace 高一些(不需要正则引擎),代码也更直观。

不止一处:建议全站搜索 ereg_replace

刚才修的只是 config.php 里的一处,DedeCMS 的源码里其实还有很多地方在用 ereg_replacesplit。如果只改这一处,后台进入「采集」「附件管理」等模块时还会冒出新的报错。我推荐用 grep 全站扫一遍:

# Linux 下递归搜索所有 PHP 文件中的 ereg_replace
grep -rn "ereg_replace" /home/wwwroot/your-site/ --include="*.php"

# 也可以同时搜索其他已废弃函数
grep -rnE "ereg_replace|eregi|eregi_replace|split|sql_regcase" /home/wwwroot/your-site/ --include="*.php"

搜出来的每一处都要按上面的思路替换。如果替换量大,建议先在本地用 phpStorm 这类 IDE 做正则批量替换,再上传覆盖。改完务必通过浏览器访问后台所有常用功能至少一次,确认没有新错误冒出来。

工程化建议:长期维护老织梦站的几个原则

做了这么多年织梦,我给手上还在维护老站点的朋友几条经验:

第一,PHP 版本不要超过 5.6。织梦官方早就停更了,你强行升 PHP 7.4 或 8.x,靠手工替换几乎修不完所有兼容问题。如果空间商强制升级,要么换主机,要么考虑迁移到 Typecho、WordPress 等还在更新的 CMS。

第二,关闭前台的 Deprecated 输出。即使你修不完所有报错,至少在 php.ini 里设置 error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT,让普通访客看不到这些警告,避免影响 SEO。

第三,定期备份。织梦站点的备份要做到「数据库 + 上传目录 + 模板目录」三件套,缺一不可。我习惯用 crontab 每天凌晨打包一次到对象存储。

第四,能静态化就静态化。织梦本身就是为静态生成而设计的,把所有列表页、详情页都生成静态 HTML,可以最大程度规避 PHP 兼容性问题——即使 PHP 报错,已经生成的静态页依旧可以访问。

常见问题 FAQ

Q1:替换后保存上传,前台仍然报错怎么办?

A:先确认两件事。第一,你修改的是网站根目录下真正在跑的 config.php,而不是本地下载的副本。第二,你的服务器是否有 OPcache 缓存,如果有,需要重启 PHP-FPM 或者执行 opcache_reset() 让修改生效。

Q2:能不能直接关掉报错,不修代码?

A:技术上可以,把 error_reporting 设置成 E_ALL & ~E_DEPRECATED 就能让 Deprecated 警告不再输出。但我不推荐这么做,因为 PHP 7.0 开始这些函数会变成 Fatal Error,到时候连关都关不掉。最好趁早把代码改对。

Q3:DedeCMS 还值得继续用吗?

A:实话说不太建议继续用于新站。它最后一次较大的安全更新是很多年前了,已知的漏洞在外部扫描器上一抓一大把。老站如果短期没法迁移,可以选择「关闭后台公网访问 + 静态化前台 + 定期人工巡检」的姑息方案。新站请优先考虑 WordPress、Typecho 或者其他活跃维护的 CMS。

Q4:替换 ereg_replace 之后还会遇到 split() 报错吗?

A:会。split() 也是 POSIX 正则系列,PHP 5.3 起被废弃,PHP 7 移除。替换思路是一样的,把 split($pattern, $string) 改成 preg_split('/'.$pattern.'/', $string),注意补上正则定界符。

总结

这个报错的本质是「老代码遇到新 PHP」。最稳的解决方式是按本文方法替换源码;最一劳永逸的方式是把站点迁移到一个还在维护的 CMS 上。无论你选哪条路,都建议先做完整备份再动手——织梦的目录结构和数据库耦合度比较高,一旦改错恢复起来挺折腾。希望本文能帮你顺利跨过这一关。

分享到
标签
版权声明

本文标题:《DedeCMS 报 ereg_replace deprecated 的根因与修复》

本文链接:https://zhangwenbao.com/dedecms-function-ereg-replace-is-deprecated.html

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

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