2009-12-16 5 views
8

Bitte siehe unten meinen Code. Ich versuche, ein Array von Parametern an meine vorbereitete Anweisung zu binden. Ich habe mich im Internet umgesehen und kann sehen, dass ich call_user_func_array verwenden muss, aber es kann nicht funktionieren. Der Fehler, den ich bekomme, ist: "Das erste Argument wird erwartet, ein gültiger Rückruf," Array "wurde gegeben" Ich mag falsch sein, aber ich nehme an, das erste Argument kann ein Array sein und vielleicht ist diese Fehlermeldung irreführend. Ich denke, das Problem ist, dass mein Array irgendwie schuld ist. Kann jemand sehen, was ich falsch mache? Vielen Dank.MySQLI bindende Parameter mit call_user_func_array

$type = array("s", "s"); 
$param = array("string1","anotherstring"); 

$stmt = $SQLConnection->prepare("INSERT INTO mytable (comp, addl) VALUES (?,?)"); 

$params = array_merge($type, $param); 

call_user_func_array(array(&$stmt, 'bind_param'), $params); 
$SQLConnection->execute(); 
+0

ich meine Fehler sollte in der ersten Zeile angezeigt: $ type = array ("ss "); – Columbo

+0

Es sind Fälle wie diese, die mich überzeugt haben, PDO gegenüber MySQL zu bevorzugen. –

Antwort

9

würde ich nicht wissen, warum Sie Verwendung call_user_func_array haben , aber das ist eine andere Geschichte.

Das einzige, was in meinen Augen falsch sein könnte, ist, dass Sie einen Verweis auf das Objekt verwenden. Angenommen, Sie PHP 5 * verwenden, das ist nicht notwendig:

call_user_func_array(array($stmt, 'bind_param'), $params); 
+0

Danke Franz, ich benutze die call_user_func_array, weil die Anzahl der zu bindenden Parameter variiert. Ich benutze PHP5, aber das Entfernen des Referenzstabs erzeugt das gleiche Ergebnis. – Columbo

+0

Dann muss das bedeuten, dass etwas mit deinem Objekt nicht stimmt. Sehen Sie diesen PHP "Fehler" Bericht: http://bugs.php.net/bug.php?id=46229. Was gibt 'var_dump ($ stmt)' an dieser Stelle? – Franz

+0

Ja, ich bekomme nur bool (wahr), anstatt die Aussage.Nicht sicher, warum Sie einen Blick darauf werfen. Ich nehme an, es gibt mir eine WAHRHEIT, um zu sagen, dass die Vorbereitung der Aussage ein Erfolg war. Aber ich habe Leute in mehreren Beispielen gesehen, die das machen, was ich oben mache. – Columbo

16

es so sein muss:

//connect 
$mysqli = new mysqli($host, $user, $password, $db_name); 

//prepare 
$stmt = $mysqli->prepare("SELECT * FROM the_table WHERE field1= ? AND Field2= ?"); 

//Binding parameters. Types: s = string, i = integer, d = double, b = blob 
$params= array("ss","string_1","string_2"); 

//now we need to add references 
$tmp = array(); 
foreach($params as $key => $value) $tmp[$key] = &$params[$key]; 
// now us the new array 
call_user_func_array(array($stmt, 'bind_param'), $tmp); 

$stmt->execute(); 

/* Fetch result to array */ 
$res = $stmt->get_result(); 
while($row = $res->fetch_array(MYSQLI_ASSOC)) { 
    $a_data[]=$row; 
} 
print_r($a_data); 

$stmt->close(); 
+0

Endlich konnte ich mit Hilfe dieses Beispiels mein Problem lösen. Das Problem war, dass die meisten Beispiele scheinbar hart 'params array' codieren, aber ich muss dies dynamisch basierend auf einem Post zu meiner API generieren. Ich musste eine Funktion erstellen, die die Werte aufnimmt und das params-Array erstellt, das ich dann mit dem 'call_user_function_array' verwende. Ich habe meine Lösung hier auf meine ursprüngliche Frage gestellt: [wie man Komma getrennt bindet ... mit NOT IN ...] (https://stackoverflow.com/questions/47821201/how-to-bind-comma-separated -ids-using-mysqli-stmt-bind-param-für-nicht-in-stateme? noredirect = 1 # comment82605027_47821201). –

0

Warum würden Sie call_user_func_array (array ($ statement nennen wollen, ‚bind_param '), $ bind_argumente)? Weil $ bind_arguments ein Array ist. Sie haben eine Funktion, die eine Anweisung an ihre abgefragten Parameter bindet, egal wie viele Parameter Sie sonst hätten.

Beispiel guten Code ...

<?php 
      # link 
     $dblink = new mysqli('HOSTNAME','USERNAME','PASSWORD','DATABASENAME'); 

      # example data 
     $statement = $dblink->prepare("SELECT * from Person WHERE FirstName = ? AND MiddleName = ? AND LastName = ? and Age = ?"); 
     $recordvalues = ['John', 'H.', 'Smith', 25]; 
     $sqlbindstring = "sssi"; # String, String, String, Integer example 

      # make the references 
     $bind_arguments = []; 
     $bind_arguments[] = $sqlbindstring; 
     foreach ($recordvalues as $recordkey => $recordvalue) 
     { 
      $bind_arguments[] = & $recordvalues[$recordkey]; # bind to array ref, not to the temporary $recordvalue 
     } 

      # query the db 
     call_user_func_array(array($statement, 'bind_param'), $bind_arguments);  # bind arguments 
     $statement->execute(); # run statement 
     $result = $statement->get_result(); # get results 

      # get the results 
     if($result) { 
      while ($row = $result->fetch_assoc()) { 
       print("\n\nMy row is..."); 
       print_r($row); 
      } 
     } 
    ?> 

Beispiel für schlechten Code ...

<?php 

      # Same setup as above.. 

     $statement->prepare("SELECT * from Person WHERE FirstName = ? AND MiddleName = ? AND LastName = ? and Age = ?"); 
     $statement->bind('John', 'H.", 'Smith', 25); 

    ?> 

Im ersten Beispiel: Sie können so viel oder so wenig passieren, um die Bindung zu sein done, so dass bind() nur in einer Zeile in Ihrer gesamten Anwendung aufgerufen werden kann. Das ist gut skalierbar.

Im zweiten Beispiel: Sie müssen eine bind() -Anweisung für jede mögliche Gruppe von Einfügungen für jeden möglichen Datensatz in Ihrer Datenbank schreiben. Dies ist schlecht skalierbar.

+0

Ihre Antwort ist eine Antwort auf eine andere Antwort ... –

0

Wenn Sie eine Fehlermeldung erhalten, sollten Sie dies versuchen:

call_user_func_array(array($stmt, 'bind_param'), refValues($params)); 

function refValues($arr){ 
    if (strnatcmp(phpversion(),'5.3') >= 0) { 
     $refs = array(); 
     foreach($arr as $key => $value) 
      $refs[$key] = &$arr[$key]; 
     return $refs; 
    } 
    return $arr; 
} 
1

nicht in der Lage war dies auf meine eigene Frage zu beantworten, weil es als Betrogene markiert wurde: here. Aber ich denke, dass meine endgültige Lösung, die die Antworten in dieser Frage verwendet, in meinem Anwendungsfall funktioniert, könnte für jemanden hilfreich sein.

Meine Ziele war es, einen Satz von IDs zu nehmen und sie in einer NOT IN MYSQL-Anweisung zu verwenden. Angenommen Array von 5 IDs wurde gepostet.

  1. Zählen Sie die Anzahl geschrieben IDs die ? Platzhalter für NOT IN Anweisung zu bauen. Die Verwendung von $params_count = substr(str_repeat(',?', count($array_of_ids)), 1); ergibt das Ergebnis: (?,?,?,?,?) in SQL-Anweisung verwendet werden.

  2. Make-Funktion, die IDs und Typ i oder s etc. Für mich, sie waren alle i, so dass meine Funktion ist einfacher.Rückgabe Array, das wie folgt aussieht $params= array("iiiii",1,2,3,4,5) wo der erste Wert ist der Satz von i 's und die nachfolgenden Werte sind die IDs in Abhängigkeit von insgesamt IDs in Funktion übergeben.

    function build_bind_params($values, $bind_type) { 
        $s = substr(str_repeat($bind_type, count($values)), 0); 
        $bind_array = array(); 
        $bind_array[] = $s; 
        foreach($values as $value) { 
         $bind_array[] = $value; 
        } 
        return $bind_array; 
    } 
    

$params = build_bind_params($array_of_ids, "i");

  1. Dann foreach ($params as $key => $value) $tmp[$key] = &$params[$key]; verwenden die neu $params für die Bindung richtig formatiert erstellt zu bekommen.

  2. Verwenden Sie dann call_user_func_array(array($stmt , 'bind_param') , $tmp);, um das Array ordnungsgemäß zu binden.

  3. Dann führen Sie die $stmt

1

Die meisten der oben genannten sind keine Lösungen ohne die Typen zusammen mit den Werten der Integration vor dem Hinzufügen von ihnen() call_user_func_array. Diese Lösung für mich gearbeitet:

/* create a database connection */ 
$db = new mysqli($host, $user, $password, $db_name); 

/* setup the sql, values, and types */ 
$sql="SELECT * FROM languages 
     WHERE language_code = ? 
      AND charset = ? 
     ORDER BY native_name"; 
$values = array($langCode, $charset); 
$types = "ss"; 

/* pass those variables to the execute() function defined below */ 
if ($rows = execute($sql, $values, $types)) 
{ 
    return $rows[0]; 
} 

function execute($sql, $values='', $types='') 
{ 
    /* prepare the sql before binding values and types */ 
    $stmt = $db->prepare($sql); 

    /*combine the values and types into $inputArray */ 
    $inputArray[] = &$types; 
    $j = count($values); 
    for($i=0;$i<$j;$i++){ 
    $inputArray[] = &$values[$i]; 
    } 
    /* add the combined values and types to call_user_func_array() for binding */ 
    call_user_func_array(array($stmt, 'bind_param'), $inputArray); 
    $result = $stmt->execute(); 
    return $result; 
} 

Hier ist ein Verweis auf die vollständige Beschreibung dieses Beispiel basiert auf: http://big.info/2015/08/php-use-call_user_func_array-for-variable-number-of-parameters-arrays-in-prepared-statements.html