AusWien: Probleme bei dynamisch erzeugten pepared Statements

Hallo.

Ich sitze gerade daran eine etwas größere Datenbankklasse basierend auf PHP und MySQLi zu erstellen.

Die Queries bekomme ich dynamisch erzeugt.
Sprich ich übergebe der Funktion ein Array mit den Spaltennamen, ein Array mit den Inhalten und die Art des Queries(UPDATE, SELECT oder INSERT) und er baut den Querie so wie ichs will. Mit oder ohne Platzhaltern nach Wahl.

Nun soll ein prepared Statement erzeugt werden.
Also der Query würde an die Funktion db_prepare_statement($query)
weitergegeben werden.

Jetzt habe ich aber ein Problem!
Abhängig von der "Art" (s.o.) des Queries und der Anzahl der Arrayinhalte, muss z.b. entweder bind_param oder bind_result verwendet werden. Letzteres ist ja weniger das Problem. Aber wie kann ich das ganze so anstellen, das ich bind_ soviele Variablen gebe, das der Querie bearbeitet werden kann. Sprich das ganze soll dynamisch sein.

Er kriegt ja von mir die "Art" und die Anzahl der Einträge des Arrays durch count().

Liebe Grüße,

Aus Wien ;)

  1. echo $begrüßung;

    Aber wie kann ich das ganze so anstellen, das ich bind_ soviele Variablen gebe, das der Querie bearbeitet werden kann. Sprich das ganze soll dynamisch sein.

    Siehe beispielsweise: bind_param mit Array möglich?

    echo "$verabschiedung $name";

    1. Hallo.

      Leider werde ich aus:
      http://forum.de.selfhtml.org/archiv/2009/3/t184032/

      bzw.

      http://forum.de.selfhtml.org/archiv/2008/2/t167140/

      nicht wirklich schlau.

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

      Liebe Grüße

      1. 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";