PHP + MYSQLI:Enlace de parámetro/resultado variable con declaraciones preparadas

StackOverflow https://stackoverflow.com/questions/12656

  •  08-06-2019
  •  | 
  •  

Pregunta

En un proyecto que estoy a punto de concluir, escribí e implementé una solución de mapeo relacional de objetos para PHP.Antes de que los escépticos y los soñadores griten "¿cómo diablos?", relájese: no he encontrado una manera de hacer que el enlace estático tardío funcione; simplemente estoy trabajando en ello de la mejor manera posible.

De todos modos, actualmente no estoy usando declaraciones preparadas para realizar consultas, porque no pude encontrar una manera de pasar una cantidad variable de argumentos al bind_params() o bind_result() métodos.

¿Por qué necesito admitir una cantidad variable de argumentos?Porque la superclase de mis modelos (piense en mi solución como un aspirante a PHP ActiveRecord pirateado) es donde se define la consulta, por lo que el método find(), por ejemplo, no sabe cuántos parámetros necesitaría vincular. .

Ahora, ya he pensado en crear una lista de argumentos y pasar una cadena a eval(), pero no me gusta mucho esa solución; prefiero simplemente implementar mis propios controles de seguridad y transmitir declaraciones.

¿Alguien tiene alguna sugerencia (o historias de éxito) sobre cómo hacer esto?Si puede ayudarme a resolver este primer problema, tal vez podamos abordar la vinculación del conjunto de resultados (algo que sospecho que será más difícil, o al menos consumirá más recursos si implica una consulta inicial para determinar la estructura de la tabla).

¿Fue útil?

Solución

En PHP puedes pasar un número variable de argumentos a una función o método usando call_user_func_array.Un ejemplo de método sería:

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

La función se llamará con cada miembro de la matriz pasado como su propio argumento.

Otros consejos

Tienes que asegurarte de que $array_of_params sea una matriz de enlaces a variables, no los valores en sí.Debiera ser:

$array_of_params[0] = &$param_string; //link to variable that stores types

Y luego...

$param_string .= "i";
$user_id_var = $_GET['user_id'];//
$array_of_params[] = &$user_id_var; //link to variable that stores value

De lo contrario (si se trata de una matriz de valores) obtendrá:

Advertencia de PHP:Se espera que el parámetro 2 de mysqli_stmt::bind_param() sea una referencia


Un ejemplo más:

$bind_names[] = implode($types); //putting types of parameters in a string
for ($i = 0; $i < count($params); $i++)
{
   $bind_name = 'bind'.$i; //generate a name for variable bind1, bind2, bind3...
   $$bind_name = $params[$i]; //create a variable with this name and put value in it
   $bind_names[] = & $$bind_name; //put a link to this variable in array
}

y BOOOOOM:

call_user_func_array( array ($stmt, 'bind_param'), $bind_names); 

No tengo permiso para editar, pero creo en el código.

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

La referencia delante de $stmt no es necesaria.Desde $stmt es el objeto y bindparams es el método en ese objeto, la referencia no es necesaria.Debería ser:

call_user_func_array(array($stmt, 'bindparams'), $array_of_params);

Para obtener más información, consulte el manual de PHP en Funciones de devolución de llamada."

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

No funcionó para mí en mi entorno, pero esta respuesta me puso en el camino correcto.Lo que realmente funcionó fue:

$sitesql = '';
$array_of_params = array();
foreach($_POST['multiselect'] as $value){
    if($sitesql!=''){
        $sitesql .= "OR siteID=? ";
        $array_of_params[0] .= 'i';
        $array_of_params[] = $value;
    }else{
        $sitesql = " siteID=? ";
        $array_of_params[0] .= 'i';
        $array_of_params[] = $value;
    }
}

$stmt = $linki->prepare("SELECT IFNULL(SUM(hours),0) FROM table WHERE ".$sitesql." AND week!='0000-00-00'");
call_user_func_array(array(&$stmt, 'bind_param'), $array_of_params);
$stmt->execute();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top