PHP语言, PHP扩展, Zend引擎相关的研究,技术,新闻分享 – 左手代码 右手诗

16 Oct 12 PDOStatement::bindParam的一个陷阱

废话不多说, 直接看代码:

$dbh = new PDO('mysql:host=localhost;dbname=test', "test");

$query = <<<QUERY
  INSERT INTO `user` (`username`, `password`) VALUES (:username, :password);
$statement = $dbh->prepare($query);

$bind_params = array(':username' => "laruence", ':password' => "weibo");
foreach( $bind_params as $key => $value ){
    $statement->bindParam($key, $value);

请问, 最终执行的SQL语句是什么, 上面的代码是否有什么问题?

Okey, 我想大部分同学会认为, 最终执行的SQL是:

INSERT INTO `user` (`username`, `password`) VALUES ("laruence", "weibo");

但是, 可惜的是, 你错了, 最终执行的SQL是:

INSERT INTO `user` (`username`, `password`) VALUES ("weibo", "weibo");


—— 如果你想自己找到原因, 那么就不要继续往下读了———

这个问题, 来自今天的一个Bug报告: #63281

究其原因, 也就是bindParam和bindValue的不同之处, bindParam要求第二个参数是一个引用变量(reference).

让我们把上面的代码的foreach拆开, 也就是这个foreach:

foreach( $bind_params as $key => $value ){
    $statement->bindParam($key, $value);


$value = $bind_params[":username"];
$statement->bindParam(":username", &$value); //此时, :username是对$value变量的引用

$value = $bind_params[":password"]; //oops! $value被覆盖成了:password的值
$statement->bindParam(":password", &$value);

所以, 在使用bindParam的时候, 尤其要注意和foreach联合使用的这个陷阱. 那么正确的作法呢?

1. 不要使用foreach, 而是手动赋值

$statement->bindParam(":username", $bind_params[":username"]); //$value是引用变量了
$statement->bindParam(":password", $bind_params[":password"]);

2. 使用bindValue代替bindParam, 或者直接在execute中传递整个参数数组.

3. 使用foreach和reference(不推荐, 原因参看:微博)

foreach( $bind_params as $key => &$value ) { //注意这里
    $statement->bindParam($key, $value);

最后, 展开了说, 对于要求参数是引用, 并且有滞后处理的函数, 都要在使用foreach的时候, 谨慎!


Related Posts:

Tags: , , , ,

63 Responses to “PDOStatement::bindParam的一个陷阱”

Pages: [2] 1 » Show All

  1. Regan Steinman |

    Si estás comenzando a aprender a tocar guitarra electrica, bien tienes una guitarra acustica, estás en el sitio indicado!

  2. Jonelle Colleano |

    Una gran forma de evaluar que el progreso es para grabar y video a ti mismo a tocar la guitarra.

  3. Jane |

    I’ll immediately snatch your rss as I can’t find your email subscription hyperlink or e-newsletter service.
    Do you’ve any? Please let me know in order that I may just subscribe.

  4. katespade |

    For the most part, life is one big trial and error. The only way you’re going to grow is to try new things and the only way to get yourself to try new things is to accept that fact that you’re going to mess up every now and then.

  5. 小小菜鸟 |


  6. PDOStatement::bindParam的一个陷阱 | 木叶下Chiang |

    [...] [...]

  7. clarence |

    ps: 窃以为php引用类型的参数时不需要加’&’,总是会很坑,真搞不懂为啥引用类型的参数为什么加’&’会被废弃

  8. xiao |


  9. PHP 最佳实践(译)一份简短的关于 PHP 容易混淆知识点的实用指南_Linux运维工程师的技术博客 |

    [...] Laruence:PDOStatement::bindParam 的一个陷阱 [...]

  10. reatang |

    我一般绑定的话,直接就把关联数组传给execute,也没用给键名加上: 就能操作。这样使用的的安全性没问题么?

  11. get adult toys online |

    Sexy lingerie when sold at wholesale rates is a very lucrative offer for any consumer.

    You would undoubtedly enjoy an enhanced charm with its lovely pink
    bowknot. The apparel industry in Australia is doing well internationally and the
    Aussie made fashion attire is now getting popular
    among international fashion freaks.

    Feel free to visit my blog post; get adult toys online

  12. gao |


  13. kaola |


Pages: [2] 1 » Show All

Leave a Reply