2009-06-14 12 views
8

ich eine SQL-Abfrage und eine Mysqli vorbereitete Anweisung haben:Wie kann ich die Ergebnisse einer vorbereiteten MySQLi-Anweisung in ein assoziatives Array einfügen?

$sql = 'SELECT photographers.photographer_id, photographers.photographer_name 
    FROM photographers'; 

$stmt = $conn->stmt_init(); 
if ($stmt->prepare($sql)) { 
    $stmt->bind_result($photographer_id, $photographer_name); 
    $OK = $stmt->execute(); 
    $stmt->fetch(); 
} 

Wie kann ich die Ergebnisse in einem assoziativen Array speichern, so kann ich Schleife später und durch die SQL-Zeichenfolge zurückgegeben auf alle Daten erhalten?

Antwort

30

Versuchen Sie Folgendes:

$meta = $statement->result_metadata(); 

while ($field = $meta->fetch_field()) { 
    $params[] = &$row[$field->name]; 
} 

call_user_func_array(array($statement, 'bind_result'), $params);    
while ($statement->fetch()) { 
    foreach($row as $key => $val) { 
     $c[$key] = $val; 
    } 
    $hits[] = $c; 
} 
$statement->close(); 

Zuerst Sie die Abfrage von Metadaten erhalten und von diesem erhalten alle Felder, die Sie geholt haben (Sie dies manuell tun könnte, aber dieser Code funktioniert für alle Abfragen, anstatt den Bau von Hand). Die call_user_func_array() Funktion ruft für jeden dieser Parameter die mysqli_stmt::bind_result() Funktion auf.

Danach ist es nur eine Frage des Durchlaufens jeder Reihe und des Erstellens eines assoziativen Feldes für jede Reihe und das Hinzufügen dieses zu einem Feld, das zu allen Resultaten führt.

+0

+1. Sehr kreativ.:) –

+0

Es ist nicht mein Code, ich kann mich nicht erinnern, wo ich es gefunden habe. Google wird zweifellos die Antwort liefern – Chris

+1

Hier gehen wir: http://us2.php.net/manual/en/mysqli-stmt.bind-result.php – Chris

1

Seltsamerweise können Sie nicht. Es gibt einfach keine Möglichkeit, ein mysqli_result-Objekt von einer mysqli_stmt-Instanz zu erhalten. Ich habe das immer als einen großen Fehler betrachtet und vermutete, dass dies einer der Hauptgründe dafür ist, dass mysqli nie wirkliche Popularität erreicht hat. In diesen Tagen wurde es von PDO ziemlich abgelöst, das tut, was Sie wollen, ohne Anstrengung.

Bearbeiten: Meine Antwort bedeutet nur, dass Sie es nicht standardmäßig tun können. Natürlich können Sie es selbst implementieren, wie Chris vorgeschlagen hat. Trotzdem, ich denke du solltest stattdessen PDO benutzen, wenn es überhaupt möglich ist.

1

Wenn Sie die PDO-Erweiterung nicht verwenden können. Oder Sie haben Probleme beim Erstellen Ihrer Datenbankklasse mit vorbereiteten Anweisungen. Wie für Insert-Update verwenden, löschen und einfügen:

$db = new database(); 
    $db->query = "INSERT INTO blabla (name,date,number) VALUES(?,?,?)"; 
    $db->params = array($name,$date,$number); 
    $db->type = 'ssi'; //s=string,i=integer 
    if($db->insert()) 
     echo 'success'; 

verschiedenen

$array = array(); 
    $db = new database(); 
    $db->query = "SELECT * FROM blabla WHERE id=? and someother=?"; 
    $db->params = array($id,$other); 
    $db->type = 'is'; 
    $r = $db->fetch(); 
    //$r[0]['id'] for row 1 
    //$r[0]['name'] for row 1 
    //$r[1] .... For row 2 
    //$r[2] .... For row 3 
    //etc... 

Jetzt für die Datenbank-Klasse

class database { 

     private $stmt; 
     private $mysqli; 
     private $query; 
     private $params = array(); 
     private $type; 

     public function __set($name, $value) { 
      switch ($name) { 
       case 'params': 
        $this->params = $value; 
        break; 
       case 'query': 
        $this->query = $value; 
        break; 
       case 'type': 
        $this->type = $value; 
        break; 
       default: 
        break; 
      } 
     } 

     public function __get($name) { 
      if ($name !== "mysqli" && $name !== "stmt") 
       return $this->$name; 
     } 

     public function __construct() { 
      $this->mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT); 
      $this->stmt = $this->mysqli->stmt_init(); 
     } 

     private function close_con($bool) { 
      if ($bool) { 
       $this->stmt->free_result(); 
      } 
      $this->stmt->close(); 
      $this->mysqli->close(); 
     } 

     private function nofetch() { 
      $this->stmt->prepare($this->query); 
      $bind_names[] = $this->type; 
      for ($i = 0; $i < count($this->params); $i++) { 
       $bind_name = 'bind' . $i; 
       $$bind_name = $this->params[$i]; 
       $bind_names[] = &$$bind_name; 
      } 
      call_user_func_array(array($this->stmt, "bind_param"), $bind_names); 

      if ($this->stmt->execute()) { 

       $this->close_con(false); 
       return true; 
      } 
      $this->close_con(false); 
      return false; 
     } 

     public function insert() { 
      if ($this->nofetch()) { 
       return true; 
      } 
      return false; 
     } 

     public function update() { 
      if ($this->nofetch()) { 
       return true; 
      } 
      return false; 
     } 

     public function delete() { 
      if ($this->nofetch()) { 
       return true; 
      } 
      return false; 
     } 

     public function fetch() { 
      $result_out = array(); 
      $this->stmt->prepare($this->query); 
      $bind_names[] = $this->type; 
      if (count($this->params) > 0) { 
       for ($i = 0; $i < count($this->params); $i++) { 
        $bind_name = 'bind' . $i; 
        $$bind_name = $this->params[$i]; 
        $bind_names[] = &$$bind_name; 
       } 
       call_user_func_array(array($this->stmt, "bind_param"), $bind_names); 
      } 
      if ($this->stmt->execute()) { 
       $result = $this->stmt->result_metadata(); 
       $cols = $result->fetch_fields(); 
       foreach ($cols as $col) { 

        $name = str_replace("-", "_", $col->name); 

        $$name = null; 
        if ($name == null) 
         $name = 'name'; 
        $bindarray[$name] = &$$name; 
       } 

       call_user_func_array(array($this->stmt, 'bind_result'), $bindarray); 
       $this->stmt->store_result(); 
       $copy = create_function('$a', 'return $a;'); 
       while ($this->stmt->fetch()) { 
        $result_out[] = array_map($copy, $bindarray); 
       } 
      } 
      $this->close_con(true); 
      return $result_out; 
     } 

    } 

Ich hoffe, dass dies hilfreich ist

Werke ein wenig Fetch
5

Aktualisierung: Seit PHP 5.3.0 kann ein mysqli_result-Objekt erhalten, das eine fetch_array-Methode bereitstellt.

$sql = 'SELECT photographers.photographer_id, photographers.photographer_name 
    FROM photographers'; 
$data = null; 

$stmt = $conn->stmt_init(); 
if ($stmt->prepare($sql)) { 
    $stmt->bind_result($photographer_id, $photographer_name); 
    $OK = $stmt->execute(); 
    $result = $stmt->get_result(); 
    $data = $result->fetch_array(); 
} 

Dokumentation: http://php.net/manual/en/mysqli-stmt.get-result.php

+3

Beachten Sie, dass dies, wie die Dokumentation sagt, nur funktioniert, wenn Sie einen nativen MySQL-Treiber installiert haben und arbeiten, den Ihre Installation möglicherweise nicht hat. – PaulJ

1

Ich kam in dieser Diskussion um Abrufen von Daten, eine Lösung zu finden, von MySQLi Aussagen ohne mysqlnd vorbereitet. Ich habe eine Klasse für den Umgang mit vorbereiteten Anweisungen mit MySQLi auf praktische Weise entwickelt. Sehen Sie sich den Code an oder verwenden Sie ihn einfach (siehe ein Anwendungsbeispiel am Ende des Codeabschnitts), um vorbereitete Anweisungen schnell zu schreiben und die Ergebnisse zu erhalten.

class DbUtils { 

    private $host; 
    private $user; 
    private $pass; 
    private $database; 
    private $connection; 

    public function __construct($host, $user, $pass, $database) { 

     $this->host = $host; 
     $this->user = $user; 
     $this->pass = $pass; 
     $this->database = $database; 
     $this->connection = new mysqli($host, $user, $pass, $database); 

    } 

    public function query(Array $params) { 

     $args = array(); 

     // 0. Correct the input function parameters 
     if (array_key_exists("query", $params)) { 
      $args["query"] = $params["query"]; 
     } else { 
      throw new Exception("Parameter not found: 'query'."); 
     } 
     if (array_key_exists("types", $params)) { 
      $args["types"] = $params["types"]; 
     } else { 
      $args["types"] = ''; 
     } 
     if (array_key_exists("input", $params)) { 
      $args["input"] = $params["input"]; 
     } else { 
      $args["input"] = array(); 
     } 

     // 1. Check the connection: 
     if ($this->connection->connect_errno) { 
      echo "Connection to MySQL failed: [" . $this->connection->connect_errno . "]: " . $this->connection->connect_error . "<br/>"; 
     } 

     // 2. Prepare the sentence: 
     if (!($stmt = $this->connection->prepare($args["query"]))) { 
      echo "Prepared statement failed: [" . $stmt->errno . "]: " . $stmt->error . "<br/>"; 
     } 

     // 3. Bind the input parameters: 
     if ((0 != sizeof($args["input"])) && !(call_user_method_array("bind_param", $stmt, array_merge(array($args["types"]), $args["input"])))) { 
      echo "Binding parameters failed: [" . $stmt->errno . "]: " . $stmt->error . "<br/>"; 
     } 

     // 4. Execute the sentence 
     if (!($stmt->execute())) { 
      echo "Sentence execution failed: [" . $stmt->errno . "]: " . $stmt->error . "<br/>"; 
     } 

     // 5. Bind the results: 
     $data = array(); 
     $meta = $stmt->result_metadata(); 
     $row = array(); 
     while($field = $meta->fetch_field()) { 
      $argos[] = &$row[$field->name]; 
     } 
     call_user_method_array('bind_result', $stmt, $argos); 

     // 6. Collect the results: 
     while ($stmt->fetch()) { 
      foreach($argos as $key => $val) { 
       $dataItem[$key] = $val; 
      } 
      $data[] = $dataItem; 
     } 

     // 7. Close the sentence: 
     $stmt->close(); 

     // 8. Return interesting data properly ordered: 
     return $data; 
    } 

} 

// 1. Instantiate it: 
$dbUtils = new DbUtils(
    "127.0.0.1", 
    "user", 
    "password", 
    "database" 
); 

// 2. Query prepared statements like this: 
$users = $dbUtils->query(array(
    "query" => "SELECT * FROM user WHERE name LIKE ? AND pass LIKE ?;", 
    "input" => array('%', '%'), 
    "types" => 'ss' 
)); 

// 3. Enjoy securely CRUD Ops! 
0

Eine einfache, die tatsächlich überraschend funktioniert. Ich weiß, es ist prozedural, aber immer noch:

$query = "SELECT * FROM foo WHERE bar = ?;"; 

$stmt = mysqli_prepare($dbc, $query); 

mysqli_stmt_bind_param($stmt, "s", $bar); 

mysqli_stmt_execute($stmt); 

$result = mysqli_stmt_get_result($stmt); 

return mysqli_fetch_assoc($result); 
Verwandte Themen