111 votes

Pourquoi j'obtiens l'erreur Cannot pass parameter 2 by reference lorsque j'utilise bindParam avec une valeur constante ?

J'utilise ce code et je suis au-delà de la frustration :

try {
    $dbh = new PDO('mysql:dbname=' . DB . ';host=' . HOST, USER, PASS);
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
}
catch(PDOException $e)
{
    ...
}
$stmt = $dbh->prepare('INSERT INTO table(v1, v2, ...) VALUES(:v1, :v2, ...)');
$stmt->bindParam(':v1', PDO::PARAM_NULL); // --> Here's the problem

PDO::PARAM_NULL, null, '', toutes échouent et produisent cette erreur :

Erreur fatale : Impossible de passer le paramètre 2 par référence dans /opt/...

144voto

JasonWoof Points 2223

Vous devez utiliser bindValue pas bindParam

bindParam prend une variable par référence, et ne prend pas de valeur au moment de l'appel à bindParam . J'ai trouvé ceci dans un commentaire sur la documentation de PHP :

bindValue(':param', null, PDO::PARAM_INT);

P.S. Vous pourriez être tenté de faire ceci bindValue(':param', null, PDO::PARAM_NULL); mais cela n'a pas fonctionné pour tout le monde (merci à Will Shaver pour son rapport).

0 votes

Je ne suis pas sûr de la différence entre les deux, mais je vais faire des recherches. Merci, votre réponse était excellente aussi.

3 votes

Je pense que cette réponse est meilleure que la mienne (si elle fonctionne effectivement).

0 votes

Mes tests sur PHP 5.3.8 + Mysql montrent qu'il n'y a pas de différence dans la requête générée entre les deux. La partie importante semble être que la valeur passée est NULL et non pas '' ou '0'.

49voto

Joe Philllips Points 13616

Lorsque vous utilisez bindParam() vous devez passer dans une variable, pas une constante. Donc, avant cette ligne, vous devez créer une variable et lui donner la valeur suivante null

$myNull = null;
$stmt->bindParam(':v1', $myNull, PDO::PARAM_NULL);

Vous obtiendrez le même message d'erreur si vous essayez :

$stmt->bindParam(':v1', 5, PDO::PARAM_NULL);

0 votes

Vous avez raison, je viens de réaliser que je l'avais fait avant dans mon code, $null = PDO::PARAM_NULL ; merci.

1 votes

Il est préférable d'utiliser bindValue() dans ce cas, si vous avez l'intention de faire des placeholders de toute façon. bindParam() est initialement prévu pour exécuter une requête, puis changer les variables et ré-exécuter sans lier les paramètres à nouveau. bindValue() lie immédiatement, bindParam() seulement lors de l'exécution.

1 votes

J'ai découvert que null doit être en minuscule dans la ligne $myNull = null. $myNull = NULL n'a PAS fonctionné.

28voto

ChrisF Points 326

Lorsque vous utilisez INTEGER (qui peuvent être NULL ) dans MySQL, PDO a un comportement (pour moi) inattendu.

Si vous utilisez $stmt->execute(Array) vous devez spécifier le littéral NULL et ne peut donner NULL par référence variable. Cela ne fonctionnera donc pas :

// $val is sometimes null, but sometimes an integer
$stmt->execute(array(
    ':param' => $val
));
// will cause the error 'incorrect integer value' when $val == null

Mais ça va marcher :

// $val again is sometimes null, but sometimes an integer
$stmt->execute(array(
    ':param' => isset($val) ? $val : null
));
// no errors, inserts NULL when $val == null, inserts the integer otherwise

Essayé sur MySQL 5.5.15 avec PHP 5.4.1

1 votes

$stmt->execute(array( ':param' => !empty($val) ? $val : null )) ; Utilisez !empty car pour une chaîne vide, vous voudriez également définir null dans la base de données.

1 votes

@ShehzadNizamani Seulement si le type de colonne est un entier, comme dans son exemple, oui. Mais sinon isset() est mieux corrélé à NULL . Une chaîne vide est également une valeur.

0 votes

@ShehzadNizamani qu'en est-il ? 0 empty() renverra vrai pour cela. et votre code stockera null au lieu d'une valeur entière légitime de 0.

9voto

Pedro Guglielmo Points 34

Pour ceux qui ont encore des problèmes (Cannot pass parameter 2 by reference), définissez une variable avec une valeur nulle, et non pas simplement passer null à PDO :

bindValue(':param', $n = null, PDO::PARAM_INT);

J'espère que cela vous aidera.

5voto

user1719210 Points 100

J'ai eu le même problème et j'ai trouvé cette solution qui fonctionne avec bindParam :

    bindParam(':param', $myvar = NULL, PDO::PARAM_INT);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X