PHPからMySQLを利用する時は、mysqliを使うことが推奨されています。
mysqliはSQLステートメントを設定した後、パラメータマーカに対して値をバインドしてSQLを実行する流れになります。
1 2 3 | $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 2 3 4 5 6 7 8 9 10 11 | //単語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は、第一引数に関数、第二引数にパラメータを配列で指定すると、配列分の引数を関数に渡して実行してくれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | //$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のやり方 […]