概要
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;