2012年3月9日金曜日

[PHP][PDO][SQL] IN句のbindを簡単に作成する。

PHPからPDOでIN句を含むSQLを発行するとき
IN(?,?,?,?)やIN(:in_1,:in_2,:in_3)
と検索する個数分「?」なり「:in_1」なりを書かないといけない。
個数が固定であれば直書きでもいいが、checkboxから飛んできたデータなど、
不定であることが多い。
もちろんforやforeachなどループで回せば書くことはできるが少々面倒臭い。
そういう時は

//idに対してこういうデータで検索条件の値が飛んでくるとする
$data=array(2,7,14,23);

$sql='';
$where=array();

$sql.="SELECT * FROM table WHERE flag=?";
$where[]=$flag;
$sql.=" AND id IN(".substr(str_repeat(',?',count($data)),1).")";
$where=array_merge($where,$data);

$st=$pdo->prepare($sql);
$st->execute($where);

とするとループを書くことなくスマート?に記述することができる。
ざっくり解説すると
SQLを組み立てるところは、まず、データの個数をcount関数で取得し、
str_repeat関数で「,?」をデータの個数分作成する。
その状態だと「,?,?,?,?」と先頭に1個「,」が多い状態なので
それをsubstr関数で先頭1文字を切り出し、「?,?,?,?」の状態にする。
実データの方はarray_mergeを使うことでflagの検索条件の値を保持したまま
1つの配列にまとめている。
なお、$dataに何も入ってないとSQLエラーになる(IN()というふうに空のIN句になってしまうので)。
そのため、事前に$dataが空じゃないかのチェックをするなりしておいたほうがいいだろう。

ポイントとなる関数
  • str_repeat ・・・ 文字列を反復する
  • substr ・・・ 文字列の一部分を返す
  • array_merge ・・・ ひとつまたは複数の配列をマージする

0 件のコメント:

コメントを投稿