【问题标题】:Passing values to MySQL IN operation in PDO prepared statement?在 PDO 准备语句中将值传递给 MySQL IN 操作?
【发布时间】:2011-01-19 07:55:10
【问题描述】:

我有一个表单字段,它返回一个逗号分隔的字符串,我想将它传递给 PHP PDO MySQL 查询 IN 操作,但 IN 操作要求值以逗号分隔(与我的 字符串个分隔值)。

我该怎么做?

$values = $_POST['values']; # '10,5,4,3' (string)
$query = "SELECT * FROM table WHERE id IN (:values)";
$data = array( ':values' => $values );

【问题讨论】:

    标签: php mysql pdo


    【解决方案1】:

    您不能在一个占位符中传递多个值。您必须为要传递到IN () 的每个值输入不同的占位符。由于不知道会有多少个,所以使用? 而不是命名参数。

    $values = explode(',', $values) ;
    
    $placeholders = rtrim(str_repeat('?, ', count($values)), ', ') ;
    $query = "SELECT * FROM table WHERE id IN ($placeholders)";
    
    $stm = $db->prepare($query) ;
    $stm->execute($values) ;
    

    【讨论】:

    • +1 很好,但是我会执行以下操作:$values = array_filter(array_map('trim', explode(',', $values)), 'is_numeric');,您永远不知道用户输入的内容...
    • rtrim 的语法相反:应该是 rtrim(str_repeat('? ,', count($values)), ', ');。但除此之外,这是我采用的解决方案。谢谢!
    • @neezer ack,干杯。参数顺序不一致的愚蠢 php :)
    • @Alix 当然,卫生应该应用于所有用户输入.. 可能比这个问题的范围更广泛 imo,但总是好的建议。
    • 旁注,看看@mfonda 对他自己的回答的评论,以更优雅的方式来弥补$placeholders 如下:$str = str_repeat('?,', $count - 1) . '?';stackoverflow.com/questions/4729679/…
    【解决方案2】:

    单独的 PDO 无法将数组绑定到 :parameter。为此,您需要一个辅助函数。

    同样在您的示例中,文字字符串 '10,5,4,3' 将作为一个值接收。参数绑定会将其变成.. id IN ('10,5,4,3'),而不是列表比较。

    在您的情况下,解决方法是使用动态 SQL 和转义。

    $values = preg_replace('/[^\d,]/', "", $_POST['values']);
    $query = "SELECT * FROM table WHERE id IN ($values)";
    

    我个人使用的是包装器/帮助器 function,它对数组有一种特殊的语法(但实际上你并没有一个开头,所以这将是一种双重解决方法):

    db("SELECT * FROM table WHERE id IN (??)", explode(",",$values));
    

    【讨论】:

      【解决方案3】:

      诀窍是识别$values 是一组单独的值,并在设置查询时牢记这一点。如果您使用? 占位符而不是命名占位符,这更容易做到。例如,您可以执行以下操作:

      $values = explode(',', $_POST['values']); //array(10,5,4,3)
      $placeholder_string = implode(',', array_fill(0, count($values), '?')); // string '?,?,?,?'
      $query = "SELECT * FROM table WHERE id IN ($placeholder_string)";
      
      $statement = $db->prepare($query);
      $statement->execute($values);
      

      【讨论】:

      • 我看到了你的array_fill,我给你提了一个str_repeat :)
      • 老实说,我发现自己有时会这样做。它可能会无缘无故地创建一个数组,但它比创建一个字符串然后必须切断多余的字符更优雅:)
      • @Fanis 我认为这在语义上更有意义——你首先要构建正确的字符串。但是像$str = str_repeat('?,', $count - 1) . '?'; 这样的东西可能是最理想的方式,现在我想起来了。
      • 确实更高效,更优雅。我会用这个,谢谢。只需要确保在附近添加一个很好的描述性评论:)
      猜你喜欢
      • 1970-01-01
      • 2020-09-13
      • 1970-01-01
      • 1970-01-01
      • 2017-09-19
      • 2019-08-04
      • 2020-04-23
      • 2011-05-14
      • 1970-01-01
      相关资源
      最近更新 更多