2011-02-24 27 views
13

He estado aprendiendo a usar declaraciones preparadas y encuadernadas para mis consultas sql, y he salido con esto hasta ahora, funciona bien pero no es dinámico en absoluto cuando se trata de parámetros múltiples o cuando no se necesita ningún parámetro,Cómo enlazar mysqli bind_param argumentos dinámicamente en PHP?

public function get_result($sql,$parameter) 
    { 
     # create a prepared statement 
    $stmt = $this->mysqli->prepare($sql); 

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

     # 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; 
      //print_r($parameters);  
     } 


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

Así es como yo llamo las clases de objetos,

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

a veces no necesito pasar en ningún parámetro,

$sql = " 
SELECT * 
FROM root_contacts_cfm 
"; 

print_r($output->get_result($sql)); 

A veces sólo necesitan un parámetros,

$sql = " 
SELECT * 
FROM root_contacts_cfm 
WHERE root_contacts_cfm.cnt_id = ? 
ORDER BY cnt_id DESC 
"; 

print_r($output->get_result($sql,'1')); 

A veces sólo necesitan más de uno los parámetros,

$sql = " 
SELECT * 
FROM root_contacts_cfm 
WHERE root_contacts_cfm.cnt_id = ? 
AND root_contacts_cfm.cnt_firstname = ? 
ORDER BY cnt_id DESC 
"; 

print_r($output->get_result($sql,'1','Tk')); 

Por lo tanto, creo que esta línea no es lo suficientemente dinámico para las tareas dinámicas anteriores,

$stmt->bind_param("s", $parameter); 

Para construir un bind_param dinámicamente, he encontrado esto en otras publicaciones en línea.

call_user_func_array(array(&$stmt, 'bind_params'), $array_of_params); 

Y he intentado modificar un código de php.net pero estoy llegando a ninguna parte,

if (strnatcmp(phpversion(),'5.3') >= 0) //Reference is required for PHP 5.3+ 
    { 
     $refs = array(); 
     foreach($arr as $key => $value) 
      $array_of_param[$key] = &$arr[$key]; 

     call_user_func_array(array(&$stmt, 'bind_params'), $array_of_params); 

    } 

¿Por qué? ¿Alguna idea de cómo puedo hacer que funcione?

¿O tal vez hay mejores soluciones?

Respuesta

17

encontró la respuesta para mysqli:

public function get_result($sql,$types = null,$params = null) 
    { 
     # create a prepared statement 
     $stmt = $this->mysqli->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; 
      //print_r($parameters);  
     } 


     # the commented lines below will return values but not arrays 
     # bind result variables 
     //$stmt->bind_result($id); 

     # fetch value 
     //$stmt->fetch(); 

     # return the value 
     //return $id; 

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

a continuación:

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

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

$sql = " 
SELECT * 
FROM root_contacts_cfm 
WHERE root_contacts_cfm.cnt_id = ? 
ORDER BY cnt_id DESC 
"; 

print_r($output->get_result($sql,'s',array('1'))); 

$sql = " 
SELECT * 
FROM root_contacts_cfm 
WHERE root_contacts_cfm.cnt_id = ? 
AND root_contacts_cfm.cnt_firstname = ? 
ORDER BY cnt_id DESC 
"; 

print_r($output->get_result($sql, 'ss',array('1','Tk'))); 

mysqli es tan cojo cuando se trata de esto. ¡Creo que debería migrar a PDO!

+0

Los valores nulos en su matriz params romperán su llamada dinámica de enlace FYI –

3

¿O tal vez hay mejores soluciones?

esta pregunta en realidad no le ayuda mucho, pero se debe considerar seriamente la posibilidad de cambiar a PDO de mysqli.

La razón principal de esto es porque PDO hace lo que está tratando de hacer en mysqli con funciones incorporadas. Además de tener manual param binding, el execute method puede tomar una matriz de argumentos en su lugar.

PDO es fácil de extender, y la adición de métodos de conveniencia para buscar-todo-y-devolver en lugar de hacer la danza de preparar-ejecutar es muy fácil.

+0

El problema es que PDO es ** ** mucho más lento que mysqli. E incluso más lento que el antiguo mysql. –

+1

@Julian: Decir 'PDO' es _much_ más lento [es demasiado] (http://jnrbsn.com/2010/06/mysqli-vs-pdo-benchmarks). La diferencia en el rendimiento es demasiado pequeña como para ser el principal cuello de botella (si es que se nota) –

+1

Gracias por corregir. Leí un punto de referencia donde la diferencia era más significativa. Y mis propias pruebas tuvieron resultados más notables. –

5

Usando PHP 5.6 puede hacer esto fácil con la ayuda de unpacking operator (...$var) y usar get_result() insted de bind_result()

public function get_result($sql,$types = null,$params = null) { 
    $stmt = $this->mysqli->prepare($sql); 
    $stmt->bind_param($types, ...$params); 

    if(!$stmt->execute()) return false; 
    return $stmt->get_result(); 

} 

Ejemplo:

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


$sql = "SELECT * FROM root_contacts_cfm WHERE root_contacts_cfm.cnt_id = ? 
     AND root_contacts_cfm.cnt_firstname = ? 
     ORDER BY cnt_id DESC"; 

$res = $output->get_result($sql, 'ss',array('1','Tk')); 
while($row = res->fetch_assoc()){ 
    echo $row['fieldName'] .'<br>'; 
} 
Cuestiones relacionadas