PHPで配列の要素数と同じ数のプレースホルダを生成する方法
PHPからSQLを作る
ことの発端は、PHPからDBにアクセスしデータを抽出するためにSQLを書くのだが、取得している配列の要素を全て条件に加えたい。
要素数によってプレースホルダの数も変化するので、 動的にプレースホルダを生成する必要がある。その生成方法の話。
やりたいこと
やりたいことは['aa', 'bb', 'cc']
こんな配列があったときに、
SELECT * FROM hoge_table WHERE hoge_id IN ('aa', 'bb', 'cc');
PHPでこんなSQLを作りたい。
もちろんこのままだとSQLインジェクションを招くので、プレースホルダで置き換えて、
<?php 'SELECT * FROM hoge_table WHERE hoge_id IN (?, ?, ?)', array('aa', 'bb', 'cc') ?>
こうしたい。どうするか?
方法1(駄目な方法)
頭使わずに直接的に生成した方法。
foreach
で繰り返し処理させており、その上if
文で判定もしていて処理の回数が多い。
<?php $arrVal = array('aa', 'bb', 'cc'); $where = 'hoge_id in ('; $arrIds = explode(',', $arrVal); foreach ($arrIds as $key => $val) { // 途中の場合','でつなぐ if ($key + 1 != count($arrIds)) { $where .= '?, '; // 最後の場合')'で閉じる } else { $where .= '?)'; } } var_dump($where); // hoge_id IN (?, ?, ?) ?>
方法2(良い方法)
改良した方法。implode
、array_fill
という2つの関数を使うと上記の処理が1行で書ける。
<?php $arrVal = array('aa', 'bb', 'cc'); $where = 'hoge_id IN (' . implode(',', array_fill(0, count($arrVal), '?')) . ')'; var_dump($where); // hoge_id IN (?, ?, ?) ?>
ちょっと解説する。
array_fill(0, count($arrVal), '?')
の部分で、['aa', 'bb', 'cc']
から
<?php array(3) { [0]=> string(1) "?" [1]=> string(1) "?" [2]=> string(1) "?" } ?>
という配列を生成し、この配列をimplode
関数を用いてカンマ区切りにする。
(特に説明は要らなかったか)
まとめ
PHPには組み込み関数が豊富にある。何かしたければまず探してみる。
特に配列に関する関数が多いので、絶対やるべき。
以前会社の先輩から、「配列を制するものはPHPを制す」とのお言葉をいただきました。
(某名作漫画のパクリではないよ、きっと…)
PHPはどこまでも配列との戦いなんだな。