2009-12-16 18 views
8

Por favor, consulte a continuación mi código. Estoy intentando vincular una matriz de parámetros a mi declaración preparada. He estado buscando en la web y puedo ver que tengo que usar call_user_func_array pero no puedo hacer que funcione. El error que recibo es: "Se espera que el primer argumento sea una devolución de llamada válida, 'Array' se dio" Puedo estar equivocado, pero supongo que el primer argumento puede ser una matriz y tal vez este mensaje de error es engañoso. Creo que el problema es que mi matriz es de alguna manera culpable. ¿Alguien puede ver lo que estoy haciendo mal? Gracias.Parámetros de enlace MySQL usando call_user_func_array

$type = array("s", "s"); 
$param = array("string1","anotherstring"); 

$stmt = $SQLConnection->prepare("INSERT INTO mytable (comp, addl) VALUES (?,?)"); 

$params = array_merge($type, $param); 

call_user_func_array(array(&$stmt, 'bind_param'), $params); 
$SQLConnection->execute(); 
+0

veo mi error en la primera línea debe ser: $ type = array ("ss "); – Columbo

+0

Son casos como este que me convencieron de preferir PDO sobre mysqli. –

Respuesta

9

no sabría por qué tiene que uso call_user_func_array, pero eso es otra historia.

Lo único que podría estar mal en mis ojos es que está utilizando una referencia al objeto. Suponiendo que está usando PHP 5. *, que no es necesario:

call_user_func_array(array($stmt, 'bind_param'), $params); 
+0

Gracias Franz, estoy usando call_user_func_array porque la cantidad de parámetros para vincular varía. Estoy usando PHP5 pero eliminar la referencia de estante produce el mismo resultado. – Columbo

+0

Entonces eso debe significar que algo está mal con su objeto. Vea este informe de PHP "error": http://bugs.php.net/bug.php?id=46229. ¿Qué te da 'var_dump ($ stmt)' en ese lugar? – Franz

+0

Sí, me estoy poniendo bool (cierto) en lugar de la declaración. No estoy seguro de por qué voy a echar un vistazo. Supongo que me está dando una TRUe para decir que la preparación de la declaración fue un éxito. Pero he visto personas haciendo lo que estoy haciendo arriba en varios ejemplos. – Columbo

16

Debe ser así:

//connect 
$mysqli = new mysqli($host, $user, $password, $db_name); 

//prepare 
$stmt = $mysqli->prepare("SELECT * FROM the_table WHERE field1= ? AND Field2= ?"); 

//Binding parameters. Types: s = string, i = integer, d = double, b = blob 
$params= array("ss","string_1","string_2"); 

//now we need to add references 
$tmp = array(); 
foreach($params as $key => $value) $tmp[$key] = &$params[$key]; 
// now us the new array 
call_user_func_array(array($stmt, 'bind_param'), $tmp); 

$stmt->execute(); 

/* Fetch result to array */ 
$res = $stmt->get_result(); 
while($row = $res->fetch_array(MYSQLI_ASSOC)) { 
    $a_data[]=$row; 
} 
print_r($a_data); 

$stmt->close(); 
+0

Finalmente pude resolver mi problema con la ayuda de este ejemplo. El problema ha sido que la mayoría de los ejemplos parecen codificar 'params array ', pero necesito generar esto dinámicamente en función de una publicación en mi API. Tuve que crear una función que toma los valores y construye la matriz de params que luego uso con 'call_user_function_array'. He puesto mi solución en mi pregunta original aquí: [cómo enlazar separados por comas ... con NO EN ...] (https://stackoverflow.com/questions/47821201/how-to-bind-comma-separated -ids-using-mysqli-stmt-bind-param-for-not-in-stateme? noredirect = 1 # comment82605027_47821201). –

0

¿Por qué quieres llamar comunicado call_user_func_array (array ($, 'bind_param '), $ bind_arguments)? Porque $ bind_arguments es una matriz. Tienes que tener una función que vincula una declaración a sus parámetros consultados, sin importar cuántos parámetros tendrías de otra manera.

Ejemplo de buen código ...

<?php 
      # link 
     $dblink = new mysqli('HOSTNAME','USERNAME','PASSWORD','DATABASENAME'); 

      # example data 
     $statement = $dblink->prepare("SELECT * from Person WHERE FirstName = ? AND MiddleName = ? AND LastName = ? and Age = ?"); 
     $recordvalues = ['John', 'H.', 'Smith', 25]; 
     $sqlbindstring = "sssi"; # String, String, String, Integer example 

      # make the references 
     $bind_arguments = []; 
     $bind_arguments[] = $sqlbindstring; 
     foreach ($recordvalues as $recordkey => $recordvalue) 
     { 
      $bind_arguments[] = & $recordvalues[$recordkey]; # bind to array ref, not to the temporary $recordvalue 
     } 

      # query the db 
     call_user_func_array(array($statement, 'bind_param'), $bind_arguments);  # bind arguments 
     $statement->execute(); # run statement 
     $result = $statement->get_result(); # get results 

      # get the results 
     if($result) { 
      while ($row = $result->fetch_assoc()) { 
       print("\n\nMy row is..."); 
       print_r($row); 
      } 
     } 
    ?> 

Ejemplo de código malo ...

<?php 

      # Same setup as above.. 

     $statement->prepare("SELECT * from Person WHERE FirstName = ? AND MiddleName = ? AND LastName = ? and Age = ?"); 
     $statement->bind('John', 'H.", 'Smith', 25); 

    ?> 

En el primer ejemplo: Puede pasar tanto o tan poco a la encuadernación que se hecho, por lo que bind() podría ser llamado en una sola línea en toda su aplicación. Esto se escala bien

En el segundo ejemplo: debe escribir una declaración bind() para cada posible grupo de inserciones para cada posible registro en su base de datos. Esto escasea pobremente.

+0

Tu respuesta es una respuesta a otra respuesta ... –

0

Si se produce un error, debe intentar esto:

call_user_func_array(array($stmt, 'bind_param'), refValues($params)); 

function refValues($arr){ 
    if (strnatcmp(phpversion(),'5.3') >= 0) { 
     $refs = array(); 
     foreach($arr as $key => $value) 
      $refs[$key] = &$arr[$key]; 
     return $refs; 
    } 
    return $arr; 
} 
1

no fue capaz de responder a esta pregunta por mi cuenta, ya que quedó marcado como víctima: here. Pero creo que mi solución final, que utiliza las respuestas en esta pregunta, funciona en mi caso de uso, podría ser útil para alguien.

Mis objetivos eran tomar un conjunto de IDs publicados y usarlos en una declaración MYSQL NOT IN. Suponiendo una matriz de 5 identificaciones publicadas.

  1. Contar el número de ID publicado para construir el ? marcadores de posición para NOT IN comunicado. El uso de $params_count = substr(str_repeat(',?', count($array_of_ids)), 1); da el resultado: (?,?,?,?,?) para ser utilizado en la declaración de SQL.

  2. Hacer la función que lleva ID's y tipo i o s etc. Para mí, todos eran i así que mi función es más simple.array que tiene este aspecto $params= array("iiiii",1,2,3,4,5) donde el primer valor es el conjunto de i 's y los valores subsiguientes son el ID de función de total del ID pasado a la función de volver.

    function build_bind_params($values, $bind_type) { 
        $s = substr(str_repeat($bind_type, count($values)), 0); 
        $bind_array = array(); 
        $bind_array[] = $s; 
        foreach($values as $value) { 
         $bind_array[] = $value; 
        } 
        return $bind_array; 
    } 
    

$params = build_bind_params($array_of_ids, "i");

  1. A continuación, utilice foreach ($params as $key => $value) $tmp[$key] = &$params[$key]; para obtener el recién creado $params formato adecuado para la unión.

  2. A continuación, utilice call_user_func_array(array($stmt , 'bind_param') , $tmp); para enlazar adecuadamente la matriz.

  3. luego ejecutar el $stmt

1

La mayoría de los anteriores no son soluciones sin integrar los tipos junto con los valores antes de añadirlos a call_user_func_array(). Esta solución funcionó para mí:

/* create a database connection */ 
$db = new mysqli($host, $user, $password, $db_name); 

/* setup the sql, values, and types */ 
$sql="SELECT * FROM languages 
     WHERE language_code = ? 
      AND charset = ? 
     ORDER BY native_name"; 
$values = array($langCode, $charset); 
$types = "ss"; 

/* pass those variables to the execute() function defined below */ 
if ($rows = execute($sql, $values, $types)) 
{ 
    return $rows[0]; 
} 

function execute($sql, $values='', $types='') 
{ 
    /* prepare the sql before binding values and types */ 
    $stmt = $db->prepare($sql); 

    /*combine the values and types into $inputArray */ 
    $inputArray[] = &$types; 
    $j = count($values); 
    for($i=0;$i<$j;$i++){ 
    $inputArray[] = &$values[$i]; 
    } 
    /* add the combined values and types to call_user_func_array() for binding */ 
    call_user_func_array(array($stmt, 'bind_param'), $inputArray); 
    $result = $stmt->execute(); 
    return $result; 
} 

Aquí es una referencia a la descripción completa de este ejemplo se basa en: http://big.info/2015/08/php-use-call_user_func_array-for-variable-number-of-parameters-arrays-in-prepared-statements.html

Cuestiones relacionadas