PDO使ってます。

これが駄目だった。

  $limit = 2;
  $posts = $db->prepare('select * from posts limit ?');
  $posts->bindValue(1, $limit);
  $successed = $posts->execute();
  if (!$successed) {
    var_dump($posts->errorInfo());
  }
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''2'' at line 1

どうも数値2が文字列"2"になってる感じがするね。

どうもバインド時に型は明示しないといけないらしい。

  $limit = 2;
  $posts = $db->prepare('select * from posts limit ?');
  $posts->bindValue(1, $limit, PDO::PARAM_INT);
  $successed = $posts->execute();
  if (!$successed) {
    var_dump($posts->errorInfo());
  }

ああ、リファレンス見ると、たしかに型指定の初期値が文字列 $data_type = PDO::PARAM_STR になってる。アイヤー、自動だと思い込んでいたよ。

twitterで教えてもらいました。