2016-07-09 11 views
0

Dies ist eine bessere Erklärung des Problems, das ich versucht, previously zu erklären versucht.Viele PHP mysqli Abfragen von einer vorbereiteten Anweisung ohne zu wissen, wie viele Parameter

Ich möchte mehrere Abfragen auszuführen, die alle die gleiche vorbereitete Anweisung verwenden, wie so (Arbeits code):

$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; 

Ich möchte diese Logik in Funktion setzen, und es wie so verwenden:

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

ich bin fest versuchen, herauszufinden, wie die Funktion gegeben zu schreiben, dass ich nicht weiß, was $params aussehen wird. Hier ist, was ich bisher:

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

Dieser Codeabschnitt kann für Sie nützlich sein: https://gist.github.com/anonymous/8906fc8bcb87c365de3874003723309e verwenden Sie im Grunde 'Database :: Query ('UPDATE mytable SET alter =? WHERE id =?', 'Ii ', 10, 1) 'und dann' Database :: Query (' UPDATE mytable SET alter =? WHERE id =? ',' Ii ', 12, 2) '. Obwohl die Abfrage wiederholt wird, erkennt die Klasse, dass sie identisch sind und verwendet die zwischengespeicherte vorbereitete Anweisung, die bei der ersten Abfrage instanziert wurde, erneut. Das ist vielleicht nicht das, wonach Sie suchen, aber ich bin sicher, dass dieser Code Ihnen bei allem hilft, was Sie brauchen. – Havenard

+0

Danke für den Tipp. Das erneute Verwenden der zwischengespeicherten vorbereiteten Anweisung hilft. Allerdings sind die vielen Funktionsaufrufe immer noch kostspielig: Wenn ich 1M-Abfragen habe, führt sie 1M Aufrufe an Query(), an $ stmt-> bind_param, an $ stmt-> execute, an $ stmt- > get_result'. In dem angegebenen Problem ist die einzige Funktion, die 1M mal aufgerufen wird, die '$ stmt-> execute()' selbst. – BeetleJuice

+0

Ich bin sicher, dass Sie einen Weg finden können, den Code an Ihre Bedürfnisse anzupassen. – Havenard

Antwort

0

Da die spezifischen var Namen verwendet, um Parameter zu beziehen, in $stmt->bind_param(...) keine Rolle spielen, änderte ich den Eingang von einem assoziativen Array zu einem indizierten Array

Bevor:

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

Jetzt:

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

Dies macht es einfacher Schleife t Durch Parameter bei jeder Abfrage. Unten ist meine Lösung:

/* 
* 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(); 
} 

Viel Glück!

+0

Hallo Leonid. Ich habe eine Lösung (hier gepostet), die 'bind_param' nur einmal nach meiner ursprünglichen Frage aufruft. Ich habe deinen Vorschlag für Variablenvariablen von der anderen Tafel verwendet :-) – BeetleJuice

Verwandte Themen