それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

pdoのprepareで名前に数字を入れると、bindValue出来ないエラー

php の pdo でエラーがでるので数日ずっと頭を抱えてた

出てくるエラー

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

エラーは、php pdo の prepare statement で、execした時にエラーになる。

<?php
/// できる
$stmt->bindValue(":n1", $val );
$stmt->bindValue("n1", $val );
$stmt->bindValue("123n", $val );
///  出来ない
$sth->bindValue(':123', $val );
$sth->bindValue('123', $val );

エラーに気づかないわけ。

bindValue( $key, $value ) は $key が文字列だと、文字列インデックスでバインドし、ハッシュ :name から文字列キーを探す。

ところが、「数字に解釈できる文字列」だと、数字だと思って疑問符( = ? )に入れようと、該当の疑問符の数字インデックスを探す→見つからない→bindParamがありません。エラーとなる。

<?php
$sth->bindValue('123', $calories);   //
$sth->bindValue(':123', $calories);  // 123 番目を探しに行く

内部で$params[123] を探しに行く。そんなものあるわけがない。探してほしいのは $params[":123"] なんだよね 指定したけどintになる文字列だと、? を探しちゃってbindValue指定時のキーに入れられない。だからエラーになる。

しかもexecするまでわからない。(←ここが辛い)

コード作者はちゃんと値を入れてるから、値がないなんて考えないよね。でもbindValueエラーが出るんだよね。頭抱えるよね。

対策

文字列であることを明確にする

<?php
$key="123"
$sth->bindValue($key.'__', $v ); 

型変換怖い

原因がわかればなんてことないが、php7以降は「型」に強いと思ってると痛い目に遭う。

組み込み関数の型は相変わらず、自動変換される。phpは自動型推測で動いたのに、いまはソースコードに型を明示するようになったので、本当に気づかない。

とくに、SQLを自動生成してるとこのバグを踏みまくる。 随分前にこの仕様を踏んでめっちゃ頭を抱えた記憶があるのだが、7−8年越しにまた踏んで頭を抱えたので、メモ。

ここ数年はLaravelしか使わないし、PDOを素で使うことなんてないからこういうのすっかり忘れてハマりました。