dedlfix: Probleme bei dynamisch erzeugten pepared Statements

Beitrag lesen

echo $begrüßung;

MIr fehlt ein wenig die Theorie, was genau dort passieren soll.
Gibt es noch Alternativen für mein Vorhaben?

Kaum. Du brauchst mysqli_stmt::bind_param() als einen Aufruf. Du kannst Variablen nicht in mehreren Schritten anbinden. Vorgesehen ist allerdings, dass mysqli_stmt::bind_param() (und auch mysqli_stmt::bind_result(), mit dem du das nächste gleichgelagerte aber noch etwas umständlicher zu lösende Problem bekommen wirst) mit einzelnen Variablen aufgerufen wird. Ein Array mit x Elementen ist zum Beispiel nicht vorgesehen. Der Trick besteht nun darin, mit call_user_func_array() die Bind-Funktion aufzurufen und ein Array zu übergeben, dessen Elemente dann aus Sicht der Bind-Funktionen wie einzelne Variablen aussehen. Das war der einfache Teil und der sieht in Code so aus:

$params = array("foo", "bar", "qux"); // Beispiel-Werte  
array_unshift($params, str_repeat('s', count($params)));  
if (!call_user_func_array(array($stmt, 'bind_param'), $params))  
  ; // Fehlerbehandlung

In $stmt steht übrigens ein erfolgreich prepariertes Statement. Und außerdem ist der Code nur für einen einmaligen Aufruf des Statements ausgelegt. Ein mehrfacher Aufruf wie er beim INSERT mehrerer Datensätze vorkommt, muss anders angegangen werden.

In </archiv/2008/2/t167140/> steht da noch ein foreach, das jedoch beim bind_param nicht benötigt wird.

Das Auslesen des Ergebnisses ist etwas komplizierter, weil dabei Variablen an mysqli_stmt::bind_result() übergeben werden, die diese Funktion sich als Referenz merkt und in die mysqli_stmt::fetch() bei jedem Aufruf die Werte reinschreibt. Man kann dabei nicht einfach ein Array anbinden, dessen Werte müssen auch noch Variablenreferenzen sein. Und die Anzahl der Felder im Resultset muss auch noch vorher ermittelt werden.

Da </archiv/2008/2/t167140/> nicht (mehr) richtig arbeitet und in </archiv/2009/3/t184032/#m1219772> nur eine Korrektur steht, hier der relevante Code für das Fetchen in voller Länge:

if ($stmt->execute()) {  
  $values = array(); // Fetch-Zwischenspeicher  
  while ($field = $meta->fetch_field())  
    $values[$field->name] =& $values[$field->name]; // jedes Feld ist eine Referenz auf sich selbst  
  $ok = call_user_func_array(array($stmt, 'bind_result'), $values);  
  if (!$ok)  
    ; // Fehlerbehandlung einfügen  
  // fetch result  
  $rows = array();  
  while ($ok = $stmt->fetch()) {  
    $row = array();  
    foreach ($values as $key => $value) // dereference bound fetched values  
      $row[$key] = $value;  
    $rows[] = $row;  
  }  
  return $rows;  
} else  
  ; // Fehlerbehandlung einfügen

echo "$verabschiedung $name";