web-dev-qa-db-fra.com

Passe par référence problème avec PHP 5.3.1

Ok, c’est un problème étrange, alors n’hésitez pas à m’expliquer.

Nous avons mis à niveau nos serveurs de développement de PHP 5.2.5 à 5.3.1.

En chargeant notre code après le changement, nous commençons à avoir des erreurs comme:

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

la ligne mentionnée (105) est la suivante:

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

nous avons changé la ligne comme suit:

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

à ce stade (parce que allow_call_time_pass_reference) est désactivé, php lance ceci:

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

Après avoir essayé de résoudre ce problème pendant un certain temps, je suis tombé en panne et ai mis allow_call_time_pass_reference sur on.

Cela a éliminé l'avertissement Deprecated, mais maintenant l'avertissement Warning: Parameter 2 to mysqli_stmt::bind_param() expected to be a reference est lancé à chaque fois, avec ou sans le référencement.

J'ai zéro idée comment résoudre ce problème. Si la méthode cible était la mienne, je me contenterais de référencer les vars entrants dans la déclaration func, mais c'est une méthode (relativement) native (mysqli).

Quelqu'un at-il vécu cela? Comment puis-je le contourner?

Je vous remercie.

32
Spot

Vous passez un tableau d'éléments ($ passArray). Le second élément inside le tableau passé doit être une référence, car il s'agit en réalité de la liste des éléments que vous passez à la fonction.

16
Zak

Je viens de rencontrer ce même problème, en appelant bind_param via call_user_func_array et en transmettant un tableau de paramètres. La solution consiste à modifier les valeurs du tableau à référencer. Ce n'est pas élégant mais ça marche. 

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

En fait, sachez qu'il existe un bogue avec PHP 5.3.1 concernant les références et toute la famille de fonctions call:

PHP Bugs # 50394: Argument de référence converti en valeur dans __call

Le comportement que vous observez est peut-être le résultat de ce bogue et toute tentative de le corriger au niveau du code peut poser problème à long terme.

Le problème a été corrigé dans la version SVN de PHP. Jusqu'à la publication de la version 5.3.2, vous pouvez compiler une nouvelle version à utiliser ou rétrograder à une version antérieure.

6
Andrew Moore

Nous rencontrions le même problème avec ce code:

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

Ma solution consistait simplement à ignorer call_user_func et à procéder ainsi:

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

Je pense que ce qui est déconseillé est de passer une référence par une fonction. Dans la définition de la fonction, vous faites quelque chose comme:

function(&$arg) {

}

Cela ne vous aide pas beaucoup, mais vous n’avez probablement pas besoin de passer la référence de toute façon. Je suppose que vous pourriez essayer une fonction wrapper.

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

J'ai un problème similaire, le code actuel n'a pas fonctionné:

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

Il a dit que "le paramètre 2 de mysqli_stmt :: bind_param () devrait être une référence, valeur donnée"

Et puis, désespéré, j'ai essayé de prendre $ from_var et $ to_var entre guillemets. Et ça a marché!

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

J'espère que ça va aider quelqu'un, bonne chance :)

0
Kotaries

Je pense que les fonctions mysqli_bind_param() et mysqli_bind_result() sont très difficiles à utiliser. J'ai rencontré le même problème que vous avez décrit en les utilisant en combinaison avec call_user_func_array()

Ma solution consistait à cesser d'utiliser mysqli et à utiliser PDO_mysql. Son utilisation est beaucoup plus simple:

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

Cela aidera:

<?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