2009-06-14 29 views
8

Tengo una consulta SQL y una declaración preparada mysqli:¿Cómo puedo poner los resultados de una declaración preparada en MySQLi en una matriz asociativa?

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

¿Cómo puedo almacenar los resultados en una matriz asociativa, así que puede recorrer más tarde y llegar a todos los datos devueltos por la cadena SQL?

Respuesta

30

intente lo siguiente:

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

En primer lugar, obtener los metadatos de consulta y de que obtener todos los campos que ha exagerado (que podría hacer esto manualmente, pero este código funciona para todas las consultas en lugar de construir por mano). La función call_user_func_array() llama a la función mysqli_stmt::bind_result() para usted en cada uno de esos parámetros.

Después de eso, solo es cuestión de recorrer cada fila y crear una matriz asociativa para cada fila y agregarla a una matriz que dé como resultado todos los resultados.

+0

+1. Muy creativo.:) –

+0

No es mi código, no recuerdo de dónde lo encontré. Google sin duda suministrará la respuesta – Chris

+1

Aquí vamos: http://us2.php.net/manual/en/mysqli-stmt.bind-result.php – Chris

1

Por extraño que parezca, no se puede. Simplemente no hay forma de obtener un objeto mysqli_result de una instancia mysqli_stmt. Siempre he considerado esto como un error importante, y supongo que esta es una de las principales razones por las que mysqli nunca alcanzó una popularidad real. Estos días ha sido reemplazado por PDO, que hace lo que quiere sin esfuerzo.

Editar: Mi respuesta solo significa que no puede hacerlo por defecto. Por supuesto que puedes implementarlo tú mismo, como sugirió Chris. Aún así, creo que debería usar PDO en su lugar, si es posible.

1

Si no puede usar la extensión PDO. O tiene problemas para construir su clase de base de datos con declaraciones preparadas. Como utilizar para la actualización de insertar, eliminar e insertar:

$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 obras un poco diferente

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

Ahora para la clase de base de datos

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

    } 

espero que esto sea útil

5

Actualización: Dado que PHP 5.3.0 puede obtener un objeto mysqli_result que proporciona un método 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(); 
} 

Documentación: http://php.net/manual/en/mysqli-stmt.get-result.php

+3

Tenga en cuenta que, como dicen los documentos, esto solo funciona si tiene instalado y en funcionamiento el controlador nativo de MySQL, que su instalación podría no tener. – PaulJ

1

me encontré con este debate con el fin de encontrar una solución para obtener datos de MySQLi prepara declaraciones sin la mysqlnd. He estado desarrollando una clase para manejar declaraciones preparadas con MySQLi de una manera práctica. Por favor, eche un vistazo al código, o simplemente úselo (vea un ejemplo de uso al final del fragmento de código) para escribir rápidamente las declaraciones preparadas y obtener sus resultados.

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

Una simple que realmente funciona sorprendentemente. Sé que es de procedimiento, pero aún así:

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