PDOの不具合
PDOのプレースホルダが意図したとおりに動作しません…。
$stmt = $pdo->prepare('SELECT * FROM address LIMIT ?, ?');
$flag = $stmt->execute(array(0, 5));
こんな風に書くと、SQLの文法エラーと言われてしまいます。
プレースホルダを文字で指定しても駄目。
$stmt = $pdo->prepare('SELECT * FROM address LIMIT :from, :to');
$flag = $stmt->execute(array(':from' => 0, ':to' => 5));
LIMIT句以外なら、普通にプレースホルダが機能するんだけどなぁ…。
ちなみに、bindValue()
で値を指定してから execute()
を実行するようにすればLIMIT句でも大丈夫だった。
$stmt = $pdo->prepare('SELECT * FROM address LIMIT ?, ?');
$stmt->bindValue(1, 0, PDO::PARAM_INT);
$stmt->bindValue(2, 5, PDO::PARAM_INT);
$flag = $stmt->execute();
文字で指定しても当然のように動作します。
$stmt = $pdo->prepare('SELECT * FROM address LIMIT :from, :to');
$stmt->bindValue(':from', 0, PDO::PARAM_INT);
$stmt->bindValue(':to', 5, PDO::PARAM_INT);
$flag = $stmt->execute();
なかなか原因が判らなかったけど、これはPDOの不具合らしい。
- PHP Bugs: #40740: PDO::execute() errors when parameters are used in LIMIT clause
- PDOでLIMIT句のプリペアードステートメントに関する不具合?
- PDOのLIMIT句が動作しない
何とも厄介な…。公式サイトには
PDO::execute() errors when parameters are used in LIMIT clause
と書かれているので execute()
の問題らしいけど、bindValue()
を使えばバージョンに関わらず実行できる…と思っていいのかな…。
うっかりミスでSQLインジェクションが起こり得ないようにするためにプレースホルダを使っている(僕の場合は)ので、「LIMIT句に値を渡すときだけ直接指定する」という書き方は極力避けたいのだけど。