PHP 5.3.1 的引用传递问题

Posted

技术标签:

【中文标题】PHP 5.3.1 的引用传递问题【英文标题】:Pass by reference problem with PHP 5.3.1 [duplicate] 【发布时间】:2011-01-03 23:46:10 【问题描述】:

好的,这是一个奇怪的问题,所以请耐心等待我解释。

我们将开发服务器从 php 5.2.5 升级到 5.3.1。

在切换后加载我们的代码,我们开始收到如下错误:

Warning: Parameter 2 to mysqli_stmt::bind_param() expected to be a reference, value given in /home/spot/trunk/system/core/Database.class.php on line 105

提到的行(105)如下:

call_user_func_array(Array($stmt, 'bind_param'), $passArray);

我们将这一行更改为:

call_user_func_array(Array($stmt, 'bind_param'), &$passArray);

此时(因为allow_call_time_pass_reference)被关闭,php抛出这个:

Deprecated: Call-time pass-by-reference has been deprecated in /home/spot/trunk/system/core/Database.class.php on line 105

在尝试修复此问题一段时间后,我崩溃并将allow_call_time_pass_reference 设置为开启。

这消除了Deprecated 警告,但现在Warning: Parameter 2 to mysqli_stmt::bind_param() expected to be a reference 警告每次都会抛出,有或没有引用。

我对如何解决这个问题一无所知。如果目标方法是我自己的,我只会在 func 声明中引用传入的 var,但它是(相对)本机方法(mysqli)。

有人经历过吗?我怎样才能绕过它?

谢谢。

【问题讨论】:

另外,在上面的代码中 $stmt 是一个从 mysqli::prepare 返回的对象 我也遇到了这个问题,发现this的博文对我帮助很大。 【参考方案1】:

我也遇到了类似的问题,目前的代码不起作用:

$query="Select id,name FROM mytable LIMIT ?,?";
$params=Array('ii');
array_push($params,$from_var);
array_push($params,$to_var);
...
$stmt=$link->prepare("$query");
$ref=new ReflectionClass('mysqli_stmt');
$method=$ref->getMethod("bind_param");
$method->invokeArgs($stmt,$params);
...

它告诉“mysqli_stmt::bind_param() 的参数 2 应该是一个参考,给定的值”

然后,我绝望地尝试将 $from_var 和 $to_var 放在引号中。它奏效了!

$params=Array('ii');
array_push($params,"$from_var");
array_push($params,"$to_var");

希望对某人有所帮助,祝你好运:)

【讨论】:

【参考方案2】:

您正在传递一个元素数组 ($passArray)。传递的数组内部的第二个项目需要是一个引用,因为这实际上是您传递给函数的项目列表。

【讨论】:

其实你是对的。但是,引用该 var 也无济于事。嗯 好的,通过创建一个虚拟数组来解决这个问题,引用来自 main 的值。很遗憾,这必须是诚实的。 :) 谢谢! 亲爱的,我也有类似的问题。你有什么建议吗? ***.com/questions/23290490/… 这个答案正确地识别了问题,但肯定看到@Dominic的以下答案以获得解决方案。【参考方案3】:

第二个参数必须是一个数组。显然这仅在 5.3 中强制执行

【讨论】:

【参考方案4】:

这会有所帮助:

<?php
call_user_func_array(Array($stmt, 'bind_param'), array(&$passArray));

function bind_param ($val)

    $val = (is_array($val)) ? $val[0] : $val;

    // operations...


?>

【讨论】:

【参考方案5】:

我们在这段代码中遇到了同样的问题:

call_user_func(array($strCartHandler, 'CartPurchaseEvent'), $strCartEvent, $objToUser, null, $this);

我的解决方案是完全跳过 call_user_func 并执行以下操作:

$strCartHandler::CartPurchaseEvent($strCartEvent, $objToUser, null, $this);

【讨论】:

【参考方案6】:

实际上,请注意 PHP 5.3.1 存在一个关于引用和所有 call 系列函数的错误:

PHP Bugs #50394: Reference argument converted to value in __call

您看到的行为可能是此错误的结果,任何以代码方式修复它的尝试从长远来看都可能会导致问题。

该问题已在 SVN 版本的 PHP 中得到修复。在 5.3.2 发布之前,您可以编译新版本使用,也可以降级到更早的版本。

【讨论】:

【参考方案7】:

我刚刚遇到了同样的问题,通过 call_user_func_array 调用 bind_param 并传递了一个参数数组。解决方法是修改要引用的数组中的值。它并不优雅,但它有效。

call_user_func_array(array($stmt, 'bind_param'), makeValuesReferenced($passArray));

function makeValuesReferenced($arr)
    $refs = array();
    foreach($arr as $key => $value)
        $refs[$key] = &$arr[$key];
    return $refs;


【讨论】:

【参考方案8】:

我认为不推荐使用的是通过函数传递引用。在函数定义中,您可以执行以下操作:

function(&$arg) 


这对您没有多大帮助,但您可能无论如何都不需要传递参考。我想你可以尝试一个包装函数。

function wrapper($stmt, &$passArray) 
    call_user_func_array($stmt, $passArray);

【讨论】:

【参考方案9】:

我认为mysqli_bind_param()mysqli_bind_result() 函数使用起来很尴尬。我遇到了与您将它们与call_user_func_array()结合使用时描述的相同的困难

我的解决方法是停止使用 mysqli,而是使用 PDO_mysql。它的用法要简单得多:

$pdoStmt->execute( $passArray );

【讨论】:

我认为 PDO_mysql 已被弃用? 不,一点也不。到底是什么让你产生了这个想法? @Spot: php_mysql.so 不推荐(不弃用),pdo_mysql.so 非常推荐。

以上是关于PHP 5.3.1 的引用传递问题的主要内容,如果未能解决你的问题,请参考以下文章

PHP对象到底是值传递还是引用传递

是否有简单的 PHP 代码来区分“将对象作为引用传递”与“将对象引用作为值传递”?

PHP值传递和引用传递的区别

PHP函数的引用传递(地址传递)

php资源是通过引用传递的吗?

何时在 PHP 中通过引用传递