2009-04-27 5 views
6

intento utilizar la variable de unión como esta:Utilice uno bind_param() con número variable de entrada vars

$stmt = $mysqli->prepare("UPDATE mytable SET myvar1=?, myvar2=... WHERE id = ?")) { 
$stmt->bind_param("ss...", $_POST['myvar1'], $_POST['myvar2']...); 

pero algunos de los $ _POST [' ... '] podría ser vacío, así que don' Quiero actualizarlos en la base de datos.

No es práctico tener en cuenta todas las diferentes combinaciones de vacío $ _POST ['...'] y aunque puedo construir la cadena "ACTUALIZAR mi SET FIJADO ..." a mis necesidades, bind_param() es un diferente bestia.

que podría intentar la construcción de su llamada como una cadena y el uso de eval() sobre ella, pero no se siente bien :(

Respuesta

-2

construirlo como una cadena, pero ponen sus valores en una matriz y pasar a que bindd_param. (y sustituir? s por valores en su cadena SQL.

$ stmt = $ mysqli-> prepare ("ACTUALIZAR mytable SET myvar1 = ?, myvar2 = ... WHERE id =?")) { $ stmt-> bind_param ("SS ...", $ _POST [ 'MyVar1'], $ _POST [ 'myvar2'] ...);

Por ejemplo:

$args = array(); 
$sql = "UPDATE sometable SET "; 
$sep = ""; 
$paramtypes = ""; 
foreach($_POST as $key => $val) { 
    $sql .= $sep.$key." = '?'"; 
    $paramtypes .= "s"; // you'll need to map these based on name 
    array_push($args, $val); 
    $sep = ","; 
} 
$sql .= " WHERE id = ?"; 
array_push($args, $id); 
array_insert($args, $paramtypes, 0); 

$stmt = $mysqli->prepare($sql); 
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params); 
$stmt->bind_param($args); 
+1

@altCongnito hace 'array_insert() 'en realidad existe? –

+0

Usted escribió '$ sql + =' en lugar de '$ sql. =' – pmrotule

1

Es ligeramente más claro para construir su declaración utilizando una matriz:

$params = array(); 
$fragments = array(); 
foreach($_POST as $col => $val) 
{ 
    $fragments[] = "{$col} = ?"; 
    $params[] = $val; 
} 

$sql = sprintf("UPDATE sometable SET %s", implode(", ", $fragments)); 
$stmt = $mysqli->prepare($sql); 
$stmt->bind_param($params); 
+0

1 para el uso de la matriz – cgp

+0

¿Es seguro para que el usuario especifique los campos a ser actualizadas así? Solo estoy pensando, si esa fuera una tabla de usuario, y el usuario de alguna manera descubriera que había una columna que almacenaba sus privilegios de usuario, podrían escalar fácilmente sus privilegios de usuario simplemente enviando una publicación de formulario con la combinación de clave/valor correcta. – Calvin

+2

Bajo ninguna circunstancia es bueno dejar que el usuario especifique los campos. Como mínimo, debería tener una matriz $ valid_fieldnames y comprobar si (isset ($ valid_fieldnames [$ col])) como el cuerpo de foreach. (Prefiero Array ('campo' => 1, 'campo2' => 1, ...) sobre Array ('campo', 'campo2', ...) ya que isset() es más rápido que in_array().) – jmucchiello

3

Esto es lo que uso para hacer mysqli preparado estados con una cantidad variable de params. Es parte de una clase que escribí. Es exageradamente exagerado para lo que necesita, pero debe mostrarle la dirección correcta.

public function __construct($con, $query){ 
    $this->con = $con; 
    $this->query = $query; 
    parent::__construct($con, $query); 
    //We check for errors: 
    if($this->con->error) throw new Exception($this->con->error); 
} 

protected static $allowed = array('d', 'i', 's', 'b'); //allowed types 

protected static function mysqliContentType($value) { 
    if(is_string($value)) $type = 's'; 
    elseif(is_float($value)) $type = 'd'; 
    elseif(is_int($value)) $type = 'i'; 
    else throw new Exception("type of '$value' is not string, int or float"); 
    return $type; 
} 

//This function checks if a given string is an allowed mysqli content type for prepared statement (s, d, b, or i) 
protected static function mysqliAllowedContentType($s){ 
    return in_array($s, self::$allowed); 
} 

public function feed($params){ 
    //These should all be empty in case this gets used multiple times 
    $this->paramArgs = array(); 
    $this->typestring = ''; 
    $this->params = $params; 
    $this->paramArgs[0] = ''; 
    $i = 0; 
    foreach($this->params as $value){ 
     //We check the type: 
     if(is_array($value)){ 
      $temp = array_keys($value); 
      $type = $temp[0]; 
      $this->params[$i] = $value[$type]; 
      if(!self::mysqliAllowedContentType($type)){ 
       $type = self::mysqliContentType($value[$type]); 
      } 
     } 
     else{ 
      $type = self::mysqliContentType($value); 
     } 
     $this->typestring .= $type; 
     //We build the array of values we pass to the bind_params function 
     //We add a refrence to the value of the array to the array we will pass to the call_user_func_array function. Thus say we have the following 
     //$this->params array: 
      //$this->params[0] = 'foo'; 
      //$this->params[1] = 4; 
     //$this->paramArgs will become: 
      //$this->paramArgs[0] = 'si'; //Typestring 
      //$this->paramArgs[1] = &$this->params[0]; 
      //$this->paramArgs[2] = &$this->params[1]. 
     //Thus using call_user_func_array will call $this->bind_param() (which is inherented from the mysqli_stmt class) like this: 
      //$this->bind_param('si', &$this->params[0], &$this->params[1]); 
     $this->paramArgs[] = &$this->params[$i]; 
     $i++; 
    } 
    unset($i); 
    $this->paramArgs[0] = $this->typestring; 
    return call_user_func_array(array(&$this, 'bind_param'), $this->paramArgs); 
} 

que lo utilice como esto:

$prep = new theClassAboveHere($mysqli, $query); 
$prep->feed(array('string', 1, array('b', 'BLOB DATA')); 

La clase debe extender la clase mysqli_stmt.

espero que esto le ayuda en la dirección correcta.
Si quieres, también podría publicar toda la clase, incluye enlaces de resultados variables.

+1

Por favor, publique toda la clase. – svenkapudija

24

usted podría utilizar la función call_user_func_array para llamar al método bind_param con un número variable o argumentos:

$paramNames = array('myvar1', 'myvar2', /* ... */); 
$params = array(); 
foreach ($paramNames as $name) { 
    if (isset($_POST[$name]) && $_POST[$name] != '') { 
     $params[$name] = $_POST[$name]; 
    } 
} 
if (count($params)) { 
    $query = 'UPDATE mytable SET '; 
    foreach ($params as $name => $val) { 
     $query .= $name.'=?,'; 
    } 
    $query = substr($query, 0, -1); 
    $query .= 'WHERE id = ?'; 
    $stmt = $mysqli->prepare($query); 
    $params = array_merge(array(str_repeat('s', count($params))), array_values($params)); 
    call_user_func_array(array(&$stmt, 'bind_param'), $params); 
} 
+1

Solo quería mencionar que en PHP 5.3+ el código anterior no funcionará, ya que requiere valores de matriz como referencia. Ver: http://php.net/manual/de/mysqli-stmt.bind-param.php – Alex2php

+0

Luego use 'bind_values' en su lugar. – Gumbo

+0

¿Dónde puedo encontrar esto en MYSQLi? Solo lo sé de PDO. – Alex2php

-1

array_insert no existe, supongo que se refiere a alguna función hecha en casa, pero yo soy no estoy seguro exactamente lo que hace ... inserta los tipos de parámetros en la matriz en algún lugar del comienzo Conjeturaría ya que el valor 0 se pasa, pero oye, podría estar en el final también;)

+3

hmm ... ¿esto parece más un comentario que una respuesta? – kleopatra

Cuestiones relacionadas