PDOのバインド変数を使用するとうまく動作しない理由(prepare、executeを使用)

現象

下記のように処理を書いて実行しましたが、「fetchAll」で値を一つも取得できませんでした。
※赤字部分が原因(後述)

$sql = "SELECT * FROM TABLENAME WHERE ";
$sql .=" xxxID='?'";
$sql .=" AND xxxNo=?";
$sth = $dbh->prepare($sql);
$res = $sth->execute(array($xxxID, $xxxNo));
while ($row = $sth->fetchAll()) {

理由

一つ目のバインドのパラメータ「?」を「’(シングルクォーテーション)」で囲っているのが原因でした。「’?’」となっていると「?」が文字列と見なされてバインド変数が代入されず、想定したSQLを実行できていなかったようです。

下記に書き換えて修正完了です。

$sql = "SELECT * FROM TABLENAME WHERE ";
$sql .=" xxxID=?";
$sql .=" AND xxxNo=?";
$sth = $dbh->prepare($sql);
$res = $sth->execute(array($xxxID, $xxxNo));
while ($row = $sth->fetchAll())
解決方法等はここまでになります

↑ここまで問題解決できなかった場合は、私の事象とは異なるものの可能性があります。お役に立てずすみません。
もし、解決できたのであれば幸いです。

以下、余談になります

なぜ2つ目の「?」にはシングルクォーテーションがないのか?

現在、PHP5.3くらいで開発された処理をPHP7で動くように改修しています。そこでDB操作をPDOに書き換えているのですが、単純に書き換えた結果1つ目はシングルクォーテーションあり、2つ目はなしという形になりました。

おそらく1つ目が「ID」なので半角文字列、2つ目が「No」なので整数(int)であったため、2つ目にはシングルクォーテーションがなかったのかなと思います。

ちなみに「?」に変更する前は変数が指定されていて、下記のような感じでした。

$sql = "SELECT * FROM TABLENAME WHERE ";
$sql .=" xxxID='".$xxxID."'";
$sql .=" AND xxxNo=".$xxxNo;

地味にはまりました

実はこのシングルクォーテーション問題、地味にはまりました。いろいろと検証していくと時間が掛かります。

解決までの流れ

バインド変数部分を通常の変数にして、下記のように「query」で試してみたところ、正常にセレクトできました。なので、バインド変数に問題があるのは分かりました。

$sth = $dbh->query($sql);

下記のようなエラーも出ていました。

Invalid parameter number: number of bound variables does not match number of tokens・・・

PHPのエラー(一部抜粋)

「バインドされた変数とトークンの変数の数が合わない」という意味になります。

引数で渡したパラメータの数と「?」の数と同じだったので、どちらかの「?」が変数として認識されていないと推測できます。そこで2つの「?」を見比べてみると、「シングルクォーテーション」の有無の違いを発見しました。

そこで「?」の状態を合わせて試してみると、「シングルクォーテーション」を外す方で解決することができました。

最後に

やはりエラー情報は貴重な情報です。少しときはエラーを真面目に見れていないときな気がします。次何かでときは、一度休憩して、再度エラーを再検証しようかと思います。