2009-09-08 4 views
90

Je suis en utilisant ce code et je suis au-delà de la frustration:Comment insérer des valeurs NULL à l'aide de PDO?

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, '', tous échouent et jeter cette erreur:

Fatal error: Cannot pass parameter 2 by reference in /opt/...

Répondre

116

Je suis en train d'apprendre AOP, mais je pense vous devez utiliser bindValue, non bindParam

bindParam prend une variable, pour faire référence, et ne tire pas en valeur au moment de l'appel bindParam. Je l'ai trouvé dans un commentaire sur les documents php:

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

EDIT: P.S. Vous pourriez être tenté de le faire bindValue(':param', null, PDO::PARAM_NULL); mais il ne fonctionne pas pour tout le monde (merci Aurez Shaver pour les rapports.)

+0

Je ne suis pas sûr de la différence entre ces deux, mais je vais enquêter sur certains. Merci, votre réponse était bonne aussi. – Nacho

+3

Je pense que cela pourrait être une meilleure réponse que la mienne (si ça marche en effet) –

+0

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 pas '' ou '0' – Odin

42

Lorsque vous utilisez bindParam() vous devez passer dans une variable, non une constante. Alors avant de cette ligne, vous devez créer une variable et le mettre à null

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

Vous obtiendrez le même message d'erreur si vous avez essayé:

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

Vous avez raison, je viens de réaliser que je l'avais déjà fait dans mon code, $ null = PDO :: PARAM_NULL; Merci. – Nacho

+1

Il est préférable d'utiliser bindValue() dans ce cas, si vous voulez faire des espaces réservés de toute façon. bindParam() est à l'origine destiné à exécuter une requête, puis à modifier les variables et à les ré-exécuter sans relier les paramètres. bindValue() se lie immédiatement, bindParam() uniquement lors de l'exécution. –

+0

J'ai trouvé que null doit être en minuscules dans la ligne $ myNull = null. $ myNull = NULL n'a PAS fonctionné. – raphael75

24

Lors de l'utilisation INTEGER colonnes (qui peut être NULL) dans MySQL, PDO a certains (pour moi) un comportement inattendu .

Si vous utilisez $stmt->execute(Array), vous devez spécifier le littéral NULL et ne pouvez pas donner NULL par référence de variable. Donc cela ne fonctionnera 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 cela fonctionnera:

// $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é ceci sur MySQL 5.5.15 avec PHP 5.4.1

+0

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

+0

@ShehzadNizamani Uniquement si le type de colonne est un entier, comme dans son exemple, yes. Sinon, 'isset()' est mieux corrélé avec 'NULL'. Une chaîne vide est également une valeur. – StanE

5

Pour ceux qui ont encore des problèmes (Impossible de transmettre le paramètre 2 par référence), définissez une variable avec une valeur nulle, et non seulement passez la valeur null à PDO:

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

J'espère que cela aide.

3

Si vous souhaitez insérer NULL que lorsque le value est empty ou '', mais insérez le value lorsqu'il est disponible. A) Reçoit les données de formulaire à l'aide de la méthode POST et appelle la fonction insert avec ces valeurs.

insert($_POST['productId'], // Will be set to NULL if empty  
     $_POST['productName']); // Will be to NULL if empty         

B) Évalue si un champ n'a pas été rempli par l'utilisateur, et insère NULL si tel est le cas.

public function insert($productId, $productName) 
{ 
    $sql = "INSERT INTO products ( productId, productName) 
       VALUES (:productId, :productName)"; 

    //IMPORTANT: Repace $db with your PDO instance 
    $query = $db->prepare($sql); 

    //Works with INT, FLOAT, ETC. 
    $query->bindValue(':productId', !empty($productId) ? $productId : NULL, PDO::PARAM_INT); 

    //Works with strings. 
    $query->bindValue(':productName',!empty($productName) ? $productName : NULL, PDO::PARAM_STR); 

    $query->execute();  
} 

Par exemple, si l'utilisateur ne fait rien sur le terrain de la forme productName, puis $productName pas entrée sera SET mais EMPTY. Donc, vous devez vérifier si c'est empty(), et si c'est le cas, alors insérez NULL.

Testé sur PHP 5.5.17

Bonne chance,

+1

Ou, vous pouvez utiliser la fonction 'IFNULL()' de MySQL dans la chaîne de requête. Comme ceci: '$ sql =" INSERT INTO produits (productId, productName), VALEURS (IFNULL (: productId, NULL), IFNULL (: productName, NULL)) ";' – starleaf1

+0

J'aime la propreté de votre solution. Je viens de le tester, mais malheureusement, il insère des chaînes vides au lieu de NULL lorsque l'utilisateur n'écrit rien sur l'entrée. C'est juste une question de préférence, mais j'ai plutôt des valeurs NULL à la place des chaînes vides. –

6

J'ai eu le même problème et je trouve cette solution de travailler avec bindParam:

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

essayer.

$stmt->bindValue(':v1', null, PDO::PARAM_NULL); // --> insert null 
+0

Avant d'essayer de répondre à une question aussi ancienne, vous devriez d'abord lire les autres réponses. Peut-être que cela a déjà été répondu. –

Questions connexes