商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > phpEnv解决PHP Notice: Only variables should be passed by reference

phpEnv解决PHP Notice: Only variables should be passed by reference

  发布于2026-07-10 阅读(0)

扫一扫,手机访问

该错误与 phpEnv 无关,因其本质是 PHP 语言层面的引用传参语法规则:仅变量可按引用传递,表达式或函数返回值不可;phpEnv 仅切换 PHP 版本,不改变此核心语义检查,故换环境无法解决。

phpEnv解决PHP Notice: Only variables should be passed by reference

很多人遇到这个报错第一反应是换环境、改配置,折腾一圈发现还是压不住。其实问题的根子在 PHP 函数传参方式上,跟 phpEnv 半点关系都没有。

为什么 phpEnv 解决不了这个问题

phpEnv 是个本地 PHP 环境管理工具,主要帮你在不同 PHP 版本(比如 7.4、8.1、8.3)之间快速切换。但它改变不了 PHP 引擎对「引用传参」的语法检查规则。这个报错从 PHP 5.3 时代就存在了,PHP 7+ 和 PHP 8.x 全系列都有,只要 error_reporting 里包含了 E_NOTICEE_STRICT(现在已经合并到 E_ALL 里了),它就会在运行时冒出来。

换个说法:用 phpEnv 装 PHP 8.2,写 array_pop(explode('@', $str)) 一样报错。把 error_reporting 设为 0 或者只保留 E_ERROR | E_WARNING 确实能看到提示消失了,但这只是掩耳盗铃,隐患还在代码里。phpEnv 没有提供所谓的「绕过引用检查」开关——也不该有这种开关。

哪些函数会直接触发这个 Notice

问题的根源在于:这些函数内部的参数声明为引用传递(&$array),所以调用时传的必须是一个变量,不能是表达式或者函数返回值:

  • end()current()next()prev()reset() —— 数组指针操作函数
  • array_pop()array_shift()array_splice() —— 修改原数组的函数
  • mysqli_stmt::bind_param() —— 预处理绑定时,第三个及以后的参数要注意
  • preg_match() 的第三个参数 &$matches —— 如果写成 preg_match($p, $s, $arr ?? []) 就会出错

来看看典型的错误写法:

$host = end(explode('@', $email)); // ❌
$stmt->bind_param('ss', $user, md5($pass)); // ❌
preg_match('/(\d+)/', $str, $matches ?? []); // ❌

正确写法:拆成两步,显式使用变量

核心原则很简单:让被引用的参数位置上出现一个「有地址的变量名」,而不是一个临时的计算结果。

  • 先把 explode() 的结果赋给一个变量,再传给 end()array_pop()
  • 预处理绑定密码时,别在 bind_param() 里直接调用 sha1()password_hash(),要么在 SQL 里处理,要么提前算好存到变量里
  • ?? [] 或三元运算符时,确保最终传进去的是变量,不是表达式

修正后的代码:

$parts = explode('@', $email);
$host = end($parts); // ✅

$password_hash = password_hash($pass, PASSWORD_DEFAULT);
$stmt->bind_param('ss', $user, $password_hash); // ✅

$matches = [];
preg_match('/(\d+)/', $str, $matches); // ✅

容易被忽略的坑:对象属性 + 引用函数组合

比如这种写法:$row->type = end(explode(':', $row->global_id)),表面上看是在赋值操作,但 end() 需要引用一个数组,而 explode(...) 返回的是临时数组,没有变量名指向它。

这种写法在 PHP 7.4+ 会明确报 Notice,而且 IDE(比如 PhpStorm)通常不会标红——因为语法层面它是合法的,只有运行时才会暴露问题。

  • 正确的做法是先提取数组:$ids = explode(':', $row->global_id); $row->type = end($ids);
  • 如果 $row->global_id 可能为空或不是字符串,还要加 is_string() 判断,否则 explode() 本身也会发出警告
  • 别指望通过 phpEnv 切换 PHP 版本来掩盖这类逻辑问题——它暴露的是代码结构缺陷,跟环境没有关系
本文转载于:https://www.php.cn/faq/2393486.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注