web-dev-qa-db-ja.com

PHP 5.3.1で参照渡し問題

わかりました、これは奇妙な問題ですので、説明しますので、ご容赦ください。

開発サーバーを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宣言で着信変数を参照するだけですが、これは(比較的)ネイティブメソッド(mysqli)です。

誰かこれを経験しましたか?どうすれば回避できますか?

ありがとうございました。

32
Spot

要素の配列($ passArray)を渡しています。 2番目の項目inside渡された配列は参照である必要があります。これは、実際に関数に渡す項目のリストだからです。

16
Zak

これと同じ問題が発生し、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;

}
45
Dominic

実際には、PHP 5.3.1の参照とすべてのcallファミリーの関数に関するバグがあることに注意してください。

PHPバグ#50394:参照引数が__callの値に変換されます

表示されている動作はこのバグの結果である可能性があり、コードを修正しようとすると、長期的に問題が発生する可能性があります。

この問題は、SVNバージョンのPHPで修正されています。 5.3.2がリリースされるまで、新しいバージョンをコンパイルして使用したり、以前のバージョンにダウングレードしたりできます。

6
Andrew Moore

このコードで同じ問題が発生していました:

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

私の解決策は、単にスキップすることでしたcall_user_funcまとめてこれを行います:

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

非推奨となっているのは、関数を介して参照を渡すことです。関数定義では、次のようにします。

function(&$arg) {

}

これはあまり役に立ちませんが、おそらく参照を渡す必要はないでしょう。あなたはラッパー関数を試すことができると思います。

function wrapper($stmt, &$passArray) {
    call_user_func_array($stmt, $passArray);
}
2
Louis

私は同様の問題を抱えていますが、現在のコードは機能しませんでした:

$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");

うまくいけば、それは誰か、幸運を助けるでしょう:)

0
Kotaries

mysqli_bind_param()関数とmysqli_bind_result()関数は使いにくいと思います。 call_user_func_array()と組み合わせて使用​​する場合と同じ問題が発生しました

私の回避策は、mysqliの使用を停止し、代わりにPDO_mysqlを使用することでした。使い方はずっと簡単です:

$pdoStmt->execute( $passArray );
0
Bill Karwin

これは役立ちます:

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

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

    // operations...
}

?>
0
Fatalist