2011-02-24 17 views
10

Hay algo que no lo entiendo en absoluto, que es prepare y query en mysqli.MySQLi: consulta VS prepare

Ésta está utilizando mysqli::query para procesar la consulta y se ha sabido de la falta de seguridad:

public function fetch_assoc($query) 
    { 
     $result = parent::query($query); 
     //$result = self::preparedStatement($query); 
     if($result) 
     { 
      return $result->fetch_assoc(); 
     } 
     else 
     { 
      # call the get_error function 
      return self::get_error(); 
      # or: 
      # return $this->get_error(); 
     } 
    } 

este es el que tiene preparar-se unen a ejecutar, que tiene una mejor seguridad Asumo,

public function fetch_assoc_stmt($sql,$types = null,$params = null) 
    { 
     # create a prepared statement 
     $stmt = parent::prepare($sql); 

     # bind parameters for markers 
     # but this is not dynamic enough... 
     //$stmt->bind_param("s", $parameter); 

     if($types&&$params) 
     { 
      $bind_names[] = $types; 
      for ($i=0; $i<count($params);$i++) 
      { 
       $bind_name = 'bind' . $i; 
       $$bind_name = $params[$i]; 
       $bind_names[] = &$$bind_name; 
      } 
      $return = call_user_func_array(array($stmt,'bind_param'),$bind_names); 
     } 

     # execute query 
     $stmt->execute(); 

     # these lines of code below return one dimentional array, similar to mysqli::fetch_assoc() 
     $meta = $stmt->result_metadata(); 

     while ($field = $meta->fetch_field()) { 
      $var = $field->name; 
      $$var = null; 
      $parameters[$field->name] = &$$var; 
     } 

     call_user_func_array(array($stmt, 'bind_result'), $parameters); 

     while($stmt->fetch()) 
     { 
      return $parameters; 
     } 

     # close statement 
     $stmt->close(); 
    } 

Sin embargo, ambos de estos dos métodos devuelven el mismo resultado,

$mysqli = new database(DB_HOST,DB_USER,DB_PASS,DB_NAME); 

$sql = " 
SELECT * 
FROM root_contacts_cfm 
ORDER BY cnt_id DESC 
"; 
print_r($mysqli->fetch_assoc_stmt($sql)); 

print_r($mysqli->fetch_assoc($sql)); 

que Imprimir esto:

Array 
(
    [cnt_id] => 2 
    [cnt_email1] => [email protected] 
    [cnt_email2] => 
    [cnt_fullname] => Lau T 
    [cnt_firstname] => Thiam 
    [cnt_lastname] => Lau 
    [cnt_organisation] => 
    [cnt_website] => 
    [cnt_biography] => 
    [cnt_gender] => 
    [cnt_birthday] => 
    [cnt_address] => 
    [cnt_postcode] => 
    [cnt_telephone] => 
    [cnt_note] => 
    [cnt_key] => 
    [cat_id] => 
    [tcc_id] => 
    [cnt_suspended] => 0 
    [cnt_created] => 2011-02-04 00:00:00 
    [cnt_updated] => 2011-02-04 13:54:36 
) 
Array 
(
    [cnt_id] => 2 
    [cnt_email1] => [email protected] 
    [cnt_email2] => 
    [cnt_fullname] => Lau T 
    [cnt_firstname] => Thiam 
    [cnt_lastname] => Lau 
    [cnt_organisation] => 
    [cnt_website] => 
    [cnt_biography] => 
    [cnt_gender] => 
    [cnt_birthday] => 
    [cnt_address] => 
    [cnt_postcode] => 
    [cnt_telephone] => 
    [cnt_note] => 
    [cnt_key] => 
    [cat_id] => 
    [tcc_id] => 
    [cnt_suspended] => 0 
    [cnt_created] => 2011-02-04 00:00:00 
    [cnt_updated] => 2011-02-04 13:54:36 
) 

Usted debe haber notado que dentro del método de fetch_assoc_stmt No consumo fetch_assoc en absoluto. Probablemente ninguna posibilidad de usarlo como prepare usa una forma diferente de devolver el resultado.

Entonces, mi pregunta es porque el uso de prepare es mejor que query, ¿por qué debería existir fetch_assoc? ¿No deberíamos olvidarnos de eso o no debería php.net tenerlo en desuso? Es lo mismo para fetch_all - ¿por qué deberíamos tenerlo en primer lugar?

Gracias.

Respuesta

21

Las sentencias preparadas son preferibles a las consultas SQL simples cuando se utilizan parámetros para generar dinámicamente la consulta. En su ejemplo, su SQL no contiene variables, por lo que el uso de una consulta simple o una declaración preparada son funcionalmente equivalentes.

Cuando tenga que cambiar los valores de los parámetros, en la cláusula WHERE, por ejemplo, entonces preparado estados le darán mayor seguridad:

... 
WHERE col1 = ? AND col2 = ? 

Pero cuando la consulta es simple y fijo, que puede requerir menos código para usar $mysqli->query($sql) junto con fetch_assoc(). El uso de consultas directas en lugar de declaraciones preparadas no es una práctica universalmente mala, como algunos podrían hacer creer. Cuando su consulta requiere parametrización o cuando la misma consulta debe compilarse y ejecutarse repetidamente, se beneficiará de la declaración preparada.

+0

explicación bastante buena. –

+0

gracias. tiene sentido ... – laukok

+0

Cabe señalar que, si bien las declaraciones preparadas sí manejan consultas repetidas, también ofrecen una protección de inyección muy superior, así que las uso incluso cuando no necesito repetir una consulta. – meteorainer

0

Disculpa que no es una respuesta, pero no soy lo suficientemente bueno como para dejar un comentario.

Parece que hay un error en su segunda función. Su código no funcionará correctamente para las consultas que devuelven más de una fila. no debe ser que la instrucción de retorno:

while($stmt->fetch()) { 

    //to dereference 
    $row_copy = $parameters; 
    $return_array[] = $row_copy; 

} 

Y a continuación, la función debe terminar con:

return $return_array;