LoginSignup
5
3

More than 5 years have passed since last update.

PDOのbindValueでIN句を使うには一工夫が必要

Last updated at Posted at 2018-09-19

概要

PHPのPDOを使ってIN句を使うためには一工夫が必要というはなし

環境

PHP:7.2.8
MySQL:5.7.23

経緯

こんなテーブルがあって

create.sql
CREATE TABLE `history` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(11) unsigned NOT NULL,
  `action_id` int(11) unsigned NOT NULL,
  `created_at` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

こんなSQLを発行したい

select.sql
SELECT * FROM history WHERE user_id IN (1,3,5);

PHPで実装してみた

test.php
try {
  $user_id = '1,3,5';
  $dbh = new PDO('mysql:host=localhost;dbname=test', 'dbuser', 'pass');

  $sql = 'SELECT * FROM history ';
  $sql .= 'WHERE user_id IN (?)';
  $stmt = $dbh->prepare($sql);
  $stmt->bindValue(1, $user_id, PDO::PARAM_INT);
  $stmt->execute();

  var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
} catch (Exception $e) {
  print "error!! " . $e->getMessage() . PHP_EOL;
}
$dbh = null;

結果は1の結果のみしか取得できない
もしくは「Invalid datetime format〜」というエラー発生

解決方法

IN句の中に指定する?を、user_idsの数分だけ記述する。
例えば、1,3,5なら「?,?,?」

test2.php
try {
  $user_id = '1,3,5';
  $user_ids = explode(',', $user_id);
  $dbh = new PDO('mysql:host=localhost;dbname=test', 'dbuser', 'pass');

  $sql = 'SELECT * FROM history ';
  $sql .= 'WHERE user_id IN (' . substr(str_repeat(',?', count($user_ids)), 1) . ')';
  $stmt = $dbh->prepare($sql);
  $stmt->execute($user_ids);

  var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
} catch (Exception $e) {
  print "error!! " . $e->getMessage() . PHP_EOL;
}
$dbh = null;

参考
[PHP][PDO][SQL] IN句のbindを簡単に作成する。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3