解决 PHP 报错:Call to undefined function uopz_override() | Uopz7 新版用法详解

16次阅读
没有评论

最近在本地调试、写 PHP 单元测试、动态 Mock 函数时,安装了 php-uopz 扩展后,代码直接报错:

Fatal error: Uncaught Error: Call to undefined function uopz_override()

很多人以为是扩展没装成功,其实 99% 原因是 Uopz 版本过高。本文带你彻底搞懂报错原因、新旧版本区别、完整可用写法、配置项、避坑指南。

一、报错根本原因

Uopz 在 7.0 版本做了毁灭性 API 重构

Uopz 6.x 及以下:支持传统函数

  • uopz_override() 重写函数/方法
  • uopz_set_return() 劫持返回值
  • uopz_delete() 删除函数/常量

Uopz 7.0+ 新版彻底废弃以上所有旧函数

新版统一只用两个核心方法:

  • uopz_set_mock() 设置模拟/重写
  • uopz_unset_mock() 恢复原生

二、先确认你的 Uopz 版本

执行命令查看版本:

php -r "echo phpversion('uopz');"
  • 输出版本 7.x / 8.x:不支持旧写法,必须用新 API
  • 无输出:扩展根本没加载成功

三、两种解决方案(任选其一)

方案一:适配新版 Uopz7+(推荐、长期使用)

放弃 uopz_override,全面改用 uopz_set_mock,兼容所有新版 PHP7.4~PHP8.3。

1. 重写系统函数(替代 uopz_override)

<?php
// 劫持原生 strlen 函数
uopz_set_mock('strlen', function ($str) {
    return 999;
});

echo strlen('abc'); // 输出 999

// 恢复原生函数
uopz_unset_mock('strlen');
echo strlen('abc'); // 输出 3

2. 快速固定返回值(替代 uopz_set_return)

<?php
// 直接固定返回假数据,无需写闭包
uopz_set_mock('file_get_contents', 'fake remote data');
echo file_get_contents('https://www.baidu.com');

// 取消劫持
uopz_unset_mock('file_get_contents');

3. Mock 类方法

<?php
class Demo
{
    public function hello()
    {
        return '原始结果';
    }
}

// 重写类方法
uopz_set_mock(Demo::class . '::hello', function () {
    return 'Uopz Mock 结果';
});

echo (new Demo())->hello(); // 输出 Mock 结果

// 恢复原生方法
uopz_unset_mock(Demo::class . '::hello');

方案二:降级 Uopz 继续使用旧写法(uopz_override)

如果你的旧代码大量依赖uopz_override,不想改代码,可以直接降级到 6.1.11(最后一个旧 API 稳定版)

# 卸载现有新版
pecl uninstall uopz

# 安装兼容旧函数的最后版本
pecl install uopz-6.1.11

# 重启 PHP-FPM
systemctl restart php8.1-fpm

降级后即可正常使用 uopz_override / uopz_set_return / uopz_delete

四、必须配置的 php.ini 权限(关键)

无论新版旧版,不开启权限会失效或报错无权限

查看配置文件路径:

php --ini

编辑 php.ini 添加以下配置:

uopz.enable = On
uopz.allow_override = On
uopz.allow_delete = On

修改后重启服务:

# 根据你的PHP版本修改
systemctl restart php8.1-fpm

五、新版 Uopz7+ 完整对照表

旧版废弃函数 新版替代方案
uopz_override() uopz_set_mock()
uopz_set_return() uopz_set_mock()
uopz_delete() 无替代(新版禁止删除内核函数)
uopz_restore() uopz_unset_mock()

六、高频避坑总结

  • CLI 和 FPM 是两套配置:命令行能用 ≠ 网页能用,必须重启 php-fpm
  • ondrej/php 源默认安装 Uopz7+,默认无旧函数
  • 生产环境绝对禁止开启 Uopz:可动态篡改内核函数,高危漏洞
  • Uopz 仅用于:本地单元测试、接口 Mock、调试代码

七、安装验证命令

# 查看扩展是否加载
php -m | grep uopz

# 查看版本
php -r "echo phpversion('uopz');"

# 判断新版Mock函数是否可用
php -r "var_dump(function_exists('uopz_set_mock'));"

结语

uopz_override 报错不是安装失败,是版本迭代导致的 API 大变更。新项目直接用 uopz_set_mock 新标准,老项目直接降级 Uopz 6.1.11 即可快速解决。

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)
验证码