Emlog 5.3.1 兼容 PHP 8.0 错误修复
前言
2020 年 11 月 26 日,PHP 8.0.0 正式发布。笔者不是 PHP 开发者,只是随便看了一些公众号的二手消息摘编凑个热闹。记得改进中有一点是更注重安全性,类型检查及其错误异常似乎更为严格规范了,可见 PHP 欲逐步解决其广受吐槽的弱类型安全隐患历史遗留问题的决心。
笔者想看看 PHP 8 兼容性如何,感受一下性能有没有什么变化,于是下载了 PHP 8.0.0 Windows 包本地玩乐一番。
简单配置完成后运行,发现 PHP 8.0 真的是 breaking change 啊,笔者手上有的、为数不多的 PHP 应用,没有一个能在 8.0 上运行起来,纷纷 Fatal error、Deprecated、Parse error……连去年(2019 年)6 月发布的 pma (phpMyAdmin) 都无法运行。好家伙。
Emlog 5.3.1 PHP 8.0 兼容修复
之前笔者已经将自用的 Emlog 5.3.1 程序兼容修复到了 PHP 7.x 下能运行的程度,结果拿到 PHP 8.0 上试,直接空输出,连报错提示页面都没有(因为在错误拦截层之下出错了),走的很安详,是时候抛弃 Emlog 了。
结合其他 PHP 应用也不容乐观的情况,笔者感觉这回不好修了。抱着没打算能修好、纯娱乐的心态,笔者研究了一下 Emlog 5.3.1 的 PHP 8.0 兼容问题,结果发现其实问题不大,并不难修。
修复完成后,Emlog 5.3.1 运行在 PHP 8.0 上
Emlog 在 init.php
的最开头调用 error_reporting()
设置了错误级别,要排错的话,需要把级别开到 E_ALL
。
以下是截止到目前笔者发现的兼容性修复要点,修复完以后 Emlog 呈现页面没有错误了,核心功能也貌似正常,但笔者很可能遗漏功能异常没有发现,欢迎读者反馈。
笔者的 Emlog 已经解决了 PHP 7.x 的兼容问题,因此本文的兼容升级背景是从 PHP 7.x -> 8.0,以下修改内容不包含针对 7.x 的兼容改动,请读者留意。
1) __autoload 改成注册式
/include/lib/function.base.php
第一个函数,即 __autoload()
函数:
把 __autoload()
换为匿名函数,然后传给 spl_autoload_register
函数注册;修改参考如下:
// function __autoload($class) {
spl_autoload_register(function ($class) {
$class = strtolower($class);
if (file_exists(EMLOG_ROOT . '/include/model/' . $class . '.php')) {
require_once(EMLOG_ROOT . '/include/model/' . $class . '.php');
} elseif (file_exists(EMLOG_ROOT . '/include/lib/' . $class . '.php')) {
require_once(EMLOG_ROOT . '/include/lib/' . $class . '.php');
} elseif (file_exists(EMLOG_ROOT . '/include/controller/' . $class . '.php')) {
require_once(EMLOG_ROOT . '/include/controller/' . $class . '.php');
} else {
emMsg($class . '加载失败。');
}
});
2) 补上 get_magic_quotes_gpc() 这个早已恒返回 false 的桩函数
还是在 include/lib/function.base.php
,在文件开头 function doStripslashes() {}
函数声明前,补充定义纯用于兼容的桩函数 get_magic_quotes_gpc()
,恒返回 FALSE
。
if (!function_exists('get_magic_quotes_gpc')) {
function get_magic_quotes_gpc() {
return false;
}
}
3) in_array() 前检查 NULL 值
还是 include/lib/function.base.php
, 原 261 行附近, addAction()
函数内,原本的代码是:
if (!@in_array($actionFunc, $emHooks[$hook])) {
要在最前面判断 $emHooks[$hook]
是否为 NULL
,避免 in_array()
第二个参数传入 NULL
导致错误;改成:
if (!@$emHooks[$hook] || !@in_array($actionFunc, $emHooks[$hook])) {
4) 更新 passwordhash.php 密码函数库,修复登录密码错误问题
修复到上一步时,Emlog 已经可以正常呈现页面了(实际上主题还可能会出错,但这需要读者自行解决了)。但是这时候 Emlog 管理登录会失败,明明密码正确却提示“密码错误,请重新输入”,这是因为 Emlog 使用的密码哈希库(/include/lib/passwordhash.php
)不兼容 PHP 8.0,工作不正常(密码 hash 返回 *0
)导致密码校验失败。
具体是什么原因导致哈希计算失败,我就不查了,因为 Emlog 用的是开源库,名字是 phpass,库文件注释里给出了项目地址 http://www.openwall.com/phpass/;直接去 phpass 官网下载最新版本的 passwordhash.php
,替换掉 /include/lib/passwordhash.php
即可修复,Emlog 集成的 phpass 版本是上古的 0.1 版本,笔者直接换成最新的 0.5 版本,问题修复。自己改密码库费事不说,最怕改得不安全。(大概看了一眼,0.1 版本工作不正常的原因可能是判断 PHP 版本时用字符串版本号弱类型大小比较导致分支错误。)
结语
笔者暂时就只找到上述这些严重影响可用性的 Emlog 核心层面的兼容问题。实际上主题、插件层面还可能会有轻微的兼容型报错,但这需要读者自行解决了。笔者是业余人员,只是娱乐修复,难以覆盖测试到 Emlog 核心的所有代码,核心层面的兼容问题如有遗漏,欢迎读者分享交流。
本以为把 Emlog 5.3.1 从 PHP 7.x 兼容到 PHP 8.0 可能要大改,但结果并没有想象中的那么复杂。稍加修补就又给 Emlog 续上了一个 PHP 版本的支持,缝缝补补又一年,该换掉 Emlog 了。不过我猜应该不会有多少人像笔者一样这么闲,在 PHP 8 上跑 Emlog 5.3 吧,要么早迁移 Emlog 6.x 了,要么能跑上去的基本都是大佬了,自己完全改得动,所以这篇文章应该帮不到多少人了。
评论
网上还是存在有情怀的人,我也是用了emlog 5.3好多年了,新版本也交钱购买了正版,但是还是觉得5.3版好用,现在更新了PHP8后就是各种问题,这个blog确实帮到我了,目前PHP8.2正常,感谢年年姐!!
@xiaoma123:😂 能帮到有需要的朋友就好
年年姐打包一个呗,让我能直接用7/8 的php.
发表评论