2016-07-09 23 views
0

これは私が悲観的に説明しようとした問題のより良い説明ですpreviously多くのパラメータを知ることなく1つのプリペイドド・ステートメントから多くのPHP mysqliクエリを実行します

私はすべてがそう(作業コード)のように、同じプリペアドステートメントを使用して複数のクエリを実行したい:

$params = [ 
    ['age'=>10,'id'=>1], ['age'=>12,'id'=>2], 
]; 
$param_types = 'ii'; 
$sql_template = "UPDATE mytable SET age = ? WHERE id = ?"; 
$stmt = $mysqli->prepare($sql_template); 
$stmt->bind_param($param_types, $age, $id); 

foreach($params as $param): 
    $age = $param['age']; 
    $id = $param['id']; 
    $stmt->execute(); 
endforeach; 

私は関数の中で、このロジックを置くのが好き、そしてそのようにそれを使用したいです:

queries_from_template($sql_template, $params, $param_types); 

は私が$paramsがどのように見えるかを知らないことを考えると機能を記述する方法を把握しようとこだわっています。ここで私はこれまで持っているものです。

function queries_from_template($sql_template,$params,$param_types){ 

    //$mysqli is a handle to a live mysqli DB connection 
    $stmt = $mysqli->prepare($sql_template); 

    //build the array that holds the arguments of $stmt->bind_param 
    //result will be eg: ['ii', 10, 1] 
    $bind_param_args = array_merge([$param_types],array_values($params[0])); 

    //call bind_param with a dynamic number of arguments 
    call_user_func_array([$stmt,"bind_param"],$bind_param_args); 

    foreach($params as $param): 
     /* THIS IS WHERE I'M STUCK*/ 
     // I need a handle to each of the parameters that were bound with 
     // bind_param so that I can set them to the correct value 
     // on each loop before I execute. 
     // Remember I don't know how many parameters there are 

     //run query with current value of parameters 
     $stmt->execute(); 
    endforeach; 

    //todo: free results, close connection, disconnect 
} 
+0

このコードは、あなたにとって役に立ちます:https://gist.github.com/anonymous/8906fc8bcb87c365de3874003723309あなたは基本的に 'Database :: Query( 'UPDATE mytable SET age =?WHERE id =?'、 'ii '、10、1) '、次にDatabase :: Query(' UPDATE mytable SET age =?WHERE id =? '、' ii '、12,2)'のようになります。クエリが繰り返されても、クラスは同じであると認識し、最初のクエリでインスタンス化されたキャッシュされたプリペアドステートメントを再利用します。これはあなたが探しているものではないかもしれませんが、私はこのコードが必要なものを手伝ってくれることを確信しています。 – Havenard

+0

チップをありがとう。キャッシュされたプリペアドステートメントを再利用すると役立ちます。しかし、多くの関数呼び出しはまだ高価です:1Mのクエリがあれば、 'Query()'、 '$ stmt-> bind_param'、' $ stmt-> execute'、 '$ stmt- > get_result'前述の問題では、1M回と呼ばれる唯一の関数は '$ stmt-> execute()'です。 – BeetleJuice

+0

あなたのニーズに合わせてコードを修正する方法が見つかるはずです。 – Havenard

答えて

0

重要ではありません$stmt->bind_param(...)のパラメータを参照するために使用される特定のvar名いるので、私は前に連想配列からインデックス付きの配列に

を入力し変更しました:

$params = [ 
    ['age'=>10,'id'=>1], ['age'=>12,'id'=>2], 
]; 

今:

$params = [ 
    [10,1], [12,2], 
]; 

これはループtにそれが容易になります各クエリのパラメータ以下は私のソリューションです:

/* 
* Executes multiple queries from the same prepared statement 
*/ 
function queries_from_template($sql_template, $params, $param_types){ 
    $stmt = $mysqli->prepare($sql_template); 

    $handles = [];//holds references to parameters 
    for($i=0; $i<count($params[0]);$i++): 
     $varname = "param_$i"; 
     $$varname = null; //define variables $param_0, $param_1... 
     $handles[] = &$$varname; //store references to the new variables 
    endfor; 

    //call $stmt->bind_param: bind to the new variables 
    $bind_param_args = array_merge([$param_types],$handles); 
    call_user_func_array([$stmt,'bind_param'],$bind_param_args); 

    foreach($params as $param): 
     foreach($handles as $index => &$handle): 
      // assign the values for the current execute loop 
      // to the created vars ($param_0, $param_1...) 
      $handle = $param[$index]; 
     endforeach; 

     $stmt->execute(); //execute, todo: error handling   
    endforeach; 

    $stmt->close(); $mysqli->close(); 
} 
0
// Associated sets 
$params_sets = [ 
    ['age'=>10,'id'=>1], 
    ['age'=>12,'id'=>2], 
]; 

// Param names in right order 
$param_names = ['age', 'id']; 

// Param types in right order 
$param_types = 'ii'; 

// SQL template 
$sql_template = "UPDATE mytable SET age = ? WHERE id = ?"; 

$stmt = $mysqli->prepare($sql_template); 

// Ok, let's do it! 
foreach ($params_sets as $params) { 
    // Collecting parameters for bind_param function 
    // You need to do it every iteration! 
    // First parameter is $param_types 
    $bind_params = [$param_types]; 
    // Now let's add every parameter in right order using $param_names 
    foreach ($param_names as $param_name) { 
     $bind_params[] = $params[$param_name]; 
    } 
    // Ok! Call bind_param method from $stmt object with $bind_params as parameters 
    call_user_func_array([$stmt, 'bind_param'], $bind_params); 
    // And execute query 
    $stmt->execute(); 
} 

幸運!

+0

こんにちは。私は私の元の質問ごとに 'bind_param'を一度だけ呼び出す解決法(ここでもそれを掲示しました)を持っています。私は他のボードからあなたの可変変数の提案を使用しました:-) – BeetleJuice

関連する問題