2009-06-14 5 views
8

Ho una domanda di sql e una dichiarazione preparata mysqli:Come posso inserire i risultati di una istruzione preparata MySQL in un array associativo?

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

Come posso memorizzare i risultati in un array associativo in modo da posso ciclo in un secondo momento e ottenere a tutti i dati restituiti dalla stringa sql?

risposta

30

provare quanto segue:

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

prima cosa ottenere i metadati di query e da quello di ottenere tutti i campi che avete recuperato (si può fare manualmente, ma questo codice funziona per tutte le query piuttosto che costruire da mano). La funzione call_user_func_array() chiama la funzione mysqli_stmt::bind_result() per ognuno di questi parametri.

Dopodiché si tratta solo di scorrere ogni riga e creare un array associativo per ogni riga e aggiungerlo a un array che risulta in tutti i risultati.

+0

+1. Molto creativo.:) –

+0

Non è il mio codice, non riesco a ricordare da dove l'ho trovato. Google fornirà senza dubbio la risposta – Chris

+1

Qui andiamo: http://us2.php.net/manual/en/mysqli-stmt.bind-result.php – Chris

1

Stranamente, non è possibile. Semplicemente non c'è modo di ottenere un oggetto mysqli_result da un'istanza mysqli_stmt. Ho sempre considerato questo un grosso difetto, e immagino che questo sia uno dei motivi principali per cui mysqli non ha mai raggiunto una vera popolarità. In questi giorni è stato praticamente sostituito da DOP, che fa quello che vuoi senza sforzo.

Modifica: La mia risposta indica solo che non è possibile farlo per impostazione predefinita. Naturalmente puoi implementarlo da solo, come suggerito da Chris. Comunque, penso che dovresti usare PDO, se è possibile.

1

Se non è possibile utilizzare l'estensione PDO. Oppure stai riscontrando problemi nella creazione della classe del database con istruzioni preparate. Come utilizzare per l'aggiornamento inserire, cancellare e inserire:

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

Fetch opere un po 'diverso

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

Ora, per la classe di database

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

    } 

Spero che questo sia utile

5

Aggiornamento: Dal PHP 5.3.0 è possibile ottenere un oggetto mysqli_result che fornisce un metodo fetch_array.

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

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

+3

Nota che, come dicono i documenti, funziona solo se hai installato e funzionante il driver nativo MySQL, che l'installazione potrebbe non avere. – PaulJ

1

mi sono imbattuto in questa discussione, al fine di trovare una soluzione per ottenere i dati da MySQLi istruzioni preparate senza l'mysqlnd. Ho sviluppato una classe per gestire le istruzioni preparate con MySQLi in modo pratico. Per favore, date un'occhiata al codice, o semplicemente usatelo (vedete un esempio di utilizzo alla fine del pezzo di codice) per scrivere rapidamente dichiarazioni preparate e ottenere i suoi risultati.

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

Uno semplice che funziona davvero sorprendentemente. So che è procedurale, ma ancora:

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