PHP + MYSQLI:プリペアドステートメントを使用した変数パラメータ/結果バインディング
質問
これからまとめようとしているプロジェクトで、PHP 用のオブジェクト リレーショナル マッピング ソリューションを作成して実装しました。疑念を持つ人や夢想家が「一体どうやって?」と叫ぶ前に、リラックスしてください -- 私は遅延静的バインディングを機能させる方法をまだ見つけていません -- 私はできる限り最善の方法でそれを回避しているだけです。
とにかく、可変数の引数をクエリに渡す方法が思いつかなかったため、現在はクエリにプリペアドステートメントを使用していません。 bind_params()
または bind_result()
メソッド。
なぜ可変数の引数をサポートする必要があるのですか?なぜなら、私のモデルのスーパークラス (私のソリューションをハックアップした PHP ActiveRecord 候補と考えてください) がクエリを定義する場所であり、そのため、たとえば find() メソッドはバインドする必要があるパラメーターの数を知りません。 。
さて、引数リストを作成して文字列を eval() に渡すことはすでに考えましたが、その解決策はあまり好きではありません。むしろ独自のセキュリティ チェックを実装してステートメントを渡したいと考えています。
これを実現する方法について何か提案 (または成功事例) がある人はいますか?この最初の問題の解決を手伝っていただければ、結果セットのバインドに取り組むことができるかもしれません (テーブル構造を決定するための最初のクエリが含まれる場合、これはより困難であるか、少なくともより多くのリソースを消費すると思われます)。
解決
PHP では、次を使用して関数またはメソッドに可変数の引数を渡すことができます。 call_user_func_array
. 。メソッドの例は次のとおりです。
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);
この関数は、配列内の各メンバーを独自の引数として渡して呼び出されます。
他のヒント
$array_of_params が次の配列であることを確認する必要があります。 変数へのリンク, 、価値観そのものではありません。こうあるべきです:
$array_of_params[0] = &$param_string; //link to variable that stores types
その後...
$param_string .= "i";
$user_id_var = $_GET['user_id'];//
$array_of_params[] = &$user_id_var; //link to variable that stores value
それ以外の場合 (値の配列の場合)、次の結果が得られます。
PHP の警告:mysqli_stmt::bind_param() のパラメータ 2 は参照であることが期待されます
もう 1 つの例:
$bind_names[] = implode($types); //putting types of parameters in a string
for ($i = 0; $i < count($params); $i++)
{
$bind_name = 'bind'.$i; //generate a name for variable bind1, bind2, bind3...
$$bind_name = $params[$i]; //create a variable with this name and put value in it
$bind_names[] = & $$bind_name; //put a link to this variable in array
}
そしてドーンと:
call_user_func_array( array ($stmt, 'bind_param'), $bind_names);
編集は許可されていませんが、コードを信じています
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);
$stmt の前の参照は必要ありません。以来 $stmt
がオブジェクトであり、 bindparams
はそのオブジェクト内のメソッドであるため、参照は必要ありません。そのはず:
call_user_func_array(array($stmt, 'bindparams'), $array_of_params);
詳細については、次の PHP マニュアルを参照してください。 コールバック関数."
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);
私の環境ではうまくいきませんでしたが、この答えは私を正しい方向に導きました。実際に機能したのは次のとおりです。
$sitesql = '';
$array_of_params = array();
foreach($_POST['multiselect'] as $value){
if($sitesql!=''){
$sitesql .= "OR siteID=? ";
$array_of_params[0] .= 'i';
$array_of_params[] = $value;
}else{
$sitesql = " siteID=? ";
$array_of_params[0] .= 'i';
$array_of_params[] = $value;
}
}
$stmt = $linki->prepare("SELECT IFNULL(SUM(hours),0) FROM table WHERE ".$sitesql." AND week!='0000-00-00'");
call_user_func_array(array(&$stmt, 'bind_param'), $array_of_params);
$stmt->execute();