PHPからMySQLを利用する時は、mysqliを使うことが推奨されています。
mysqliはSQLステートメントを設定した後、パラメータマーカに対して値をバインドしてSQLを実行する流れになります。
$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'world'); $stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)"); $stmt->bind_param('sssd', $code, $language, $official, $percent);
このときのバインドは当然ながら、bind_paramに渡す引数の数とパラメータマーカの数が一致していないとなりません。上記で言うと、パラメータマーカ「?」が4つあるので、bind_paramには型指定の文字列と、そこにバインドする値($code, $language, $official, $percent)を順番に引数に入れるわけです。
パラメータマーカの数が変わる場合
基本にはあまりSQLにバインドする変数の数が変わることは無いと思いますが、例えば検索でLIKEやREGEXPを実行する場合に、複数単語の入力で絞り込み機能などを実装しようとすると、検索語の数が特定出来ないことがあります。
//単語1個で検索 $stmt = $mysqli->prepare("SELECT * FROM `table_name` WHERE `data_name` REGEXP ?"); $stmt->bind_param('s', $keyword1); //単語2個でAND検索 $stmt = $mysqli->prepare("SELECT * FROM `table_name` WHERE `data_name` REGEXP ? and `data_name` REGEXP ?"); $stmt->bind_param('ss', $keyword1, $keyword2); //単語3個でAND検索 $stmt = $mysqli->prepare("SELECT * FROM `table_name` WHERE `data_name` REGEXP ? and `data_name` REGEXP ? and `data_name` REGEXP ?"); $stmt->bind_param('sss', $keyword1, $keyword2, $keyword3);
検索語の数に合わせてSQL文を調整することは簡単ですが、bind_paramの引数の数を変えるのはちょっと難しいです。evalでも出来るかもしれませんが、あまり使いたくないですね。
ここは、call_user_func_arrayを使ってbind_paramを実行すると上手くいくようです。
call_user_func_arrayは、第一引数に関数、第二引数にパラメータを配列で指定すると、配列分の引数を関数に渡して実行してくれます。
//$dataの配列は要素数が可変:以下例では3つあるとする $data = array($keyword1,$keyword2,$keyword3); //SQL文を作る:キーワード分の`data_name` REGEXP ?'をandで連結 $sql = "SELECT * FROM `table_name` WHERE ". implode( ' and ', array_fill(0, count($data), '`data_name` REGEXP ?') ); $stmt = $mysqli->prepare($sql); //パラメータ用配列を作る //型指定:この例では$stmtParams[0]に'sss'が入る $stmtParams = array( str_repeat( 's', count($data) ) ); //$stmtParams[1]~にそれぞれデータを参照渡しする //※ここは参照渡しでないとNG foreach ($data as $k=>$v){ $stmtParams[] = &$data[$k]; } //call_user_func_array経由でbind_paramに渡す call_user_func_array(array($stmt, 'bind_param'), $stmtParams);
このようにすると、$dataの要素数がいくつあってもバインド出来ます。
あとは普通にexcuteするだけです。
コメント
[…] PHP/mysqliのSQLステートメントのパラメータの数が可変する時のbind_paramのやり方 […]