<p>PHP 8.0 彻底移除 mcrypt_* 和 create_function(),需分别替换为 OpenSSL 加密函数和闭包;password_hash()/verify() 仍安全可用;str_replace('', ...) 行为变更需适配。</p>

mcrypt_* 函数直接报 Fatal error 怎么办
PHP 8.0 彻底移除了 mcrypt_* 系列函数,调用即崩,不是警告而是 Fatal error: Uncaught Error: Call to undefined function mcrypt_encrypt()。别试图用 function_exists() 包一层兜底——它在 PHP 8.0 下永远返回 false,分支根本进不去。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 先定位所有调用点:
grep -r "mcrypt_" ./src/ ./vendor/ --include="*.php",重点看mcrypt_encrypt、mcrypt_decrypt、mcrypt_module_open - 确认密钥长度和算法模式:旧代码常用
MCRYPT_RIJNDAEL_128+MCRYPT_MODE_CBC,对应 OpenSSL 的aes-128-cbc;注意 IV 长度必须为 16 字节(AES-CBC 要求) - 别直接套用
openssl_encrypt()默认参数:它默认使用 PKCS#7 填充,而 mcrypt 多数是零填充(\x00),需手动处理或改用openssl_encrypt($data, 'aes-128-cbc', $key, OPENSSL_ZERO_PADDING, $iv)并自行补零
如何安全替换 create_function() 且兼容 PHP 7.3+
create_function() 在 PHP 8.0 被彻底砍掉,且本质是 eval() 封装,存在严重安全隐患。不能只改函数名,得重构作用域和执行逻辑。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 若只在当前作用域用简单回调(如
array_map),优先用箭头函数:$callback = fn($x) => strtoupper($x);(PHP 7.4+) - 若需兼容 PHP 7.3,改用匿名函数显式
use:$callback = function($x) use ($prefix) { return $prefix . strtoupper($x); }; - 避免在循环内重复定义匿名函数——性能损耗明显;提前声明再复用,例如:
$upper = fn($s) => strtoupper($s); array_map($upper, $arr); - 警惕字符串拼接构造的
create_function(),如create_function('$a', 'return ' . $expr . ';'),这类必须重写为闭包或提取为独立方法
password_hash() 和 password_verify() 还能放心用吗
能。这两个函数不仅没废弃,反而是 PHP 8 推荐的唯一密码处理方案。但要注意:它们生成的是可移植散列(如 y$...),和其他语言交互时需确认对方支持相同算法(bcrypt / Argon2)。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 别自己实现 salt 或 hash 拼接逻辑——
password_hash()自动处理 salt 和成本因子 - 验证时始终用
password_verify($input, $hash),不要用==或===直接比对散列值 - 升级已有密码:若旧系统用 md5 或 sha1 存储,可在登录成功后调用
password_hash($pwd, PASSWORD_ARGON2ID)更新到新格式(需数据库字段支持更长字符串) - 注意
password_needs_rehash():当算法或成本因子升级时,它会返回true,此时应重新 hash 并更新存储
str_replace() 在 PHP 8.0 的空字符串行为差异
这不是废弃,但极易导致逻辑错乱:str_replace('', 'x', 'abc') 在 PHP 7.x 返回 'xaxbxcx',PHP 8.0+ 直接返回原串 'abc'。很多路由分发、模板插值、URL 构造逻辑因此失效。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 检查所有含空字符串作为搜索项的
str_replace()调用,尤其是动态构建的替换逻辑 - 若确实需要“在每个字符间插入”,改用
implode('x', str_split('abc')),语义明确且跨版本一致 - 注意数组参数场景:
str_replace([''], ['x'], $str)在 PHP 8.0+ 会触发Warning: str_replace(): Empty array passed,而旧版静默忽略——务必确保搜索数组非空 - CI 流程中加运行时校验:用
php -d error_reporting=E_ALL -l扫描语法,再跑一次带-d error_reporting=E_ALL的最小测试集,捕获这类隐性变更
最常被忽略的一点:加密迁移不是单纯换函数名,得核对 IV 生成方式、填充策略、密钥派生逻辑是否一致;哪怕 OpenSSL 函数调用成功,解密失败往往是因为这些细节不匹配。



















