stmt statement sentencias prepared preparadas bind_param php sql dynamic eval prepared-statement

statement - sentencias preparadas php mysqli



¿Son las declaraciones preparadas dinámicas malas?(con php+mysqli) (2)

Creo que es peligroso usar eval() aquí.

Prueba esto:

  • iterar la matriz params para construir la cadena SQL con signos de interrogación "SELECT * FROM t1 WHERE p1 = ? AND p2 = ?"
  • llamar a prepare() en eso
  • use call_user_func_array() para hacer la llamada a bind_param() , pasando en la matriz de parámetros dinámicos.

El código:

call_user_func_array(array($stmt, ''bind_param''), array($types)+$param);

Me gusta la flexibilidad de Dynamic SQL y me gusta la seguridad + el rendimiento mejorado de las declaraciones preparadas. Entonces, lo que realmente quiero es declaraciones preparadas dinámicas, lo cual es problemático porque bind_param y bind_result aceptan una cantidad de argumentos "fija". Así que hice uso de una declaración eval () para evitar este problema. Pero tengo la sensación de que esta es una mala idea. Aquí hay un código de ejemplo de lo que quiero decir

// array of WHERE conditions $param = array(''customer_id''=>1, ''qty''=>''2''); $stmt = $mysqli->stmt_init(); $types = ''''; $bindParam = array(); $where = ''''; $count = 0; // build the dynamic sql and param bind conditions foreach($param as $key=>$val) { $types .= ''i''; $bindParam[] = ''$p''.$count.''=$param["''.$key.''"]''; $where .= "$key = ? AND "; $count++; } // prepare the query -- SELECT * FROM t1 WHERE customer_id = ? AND qty = ? $sql = "SELECT * FROM t1 WHERE ".substr($where, 0, strlen($where)-4); $stmt->prepare($sql); // assemble the bind_param command $command = ''$stmt->bind_param($types, ''.implode('', '', $bindParam).'');''; // evaluate the command -- $stmt->bind_param($types,$p0=$param["customer_id"],$p1=$param["qty"]); eval($command);

¿Es esa última declaración eval () una mala idea? Intenté evitar la inyección de código encapsulando valores detrás del nombre de la variable $ param.

¿Alguien tiene una opinión u otras sugerencias? ¿Hay algún problema que deba tener en cuenta?


Realmente no necesita declaraciones preparadas y argumentos enlazados, porque siempre puede usar mysql_real_escape_string (). Y tienes razón; SQL generado dinámicamente es mucho más flexible y valioso.

Aquí hay un ejemplo simple usando la interfaz regular mysql_ *:

// Array of WHERE conditions $conds = array("customer_id" => 1, "qty" => 2); $wherec = array("1"); foreach ($conds as $col=>$val) $wherec[] = sprintf("`%s` = ''%s''", $col, mysql_real_escape_string($val)); $result_set = mysql_query("SELECT * FROM t1 WHERE " . implode(" AND ", $wherec);

Por supuesto, este es un ejemplo simplista, y para que sea útil, debes construirlo y refinarlo mucho, pero muestra las ideas y es realmente muy útil. Por ejemplo, aquí hay una función completamente genérica para insertar una nueva fila en una tabla arbitraria, con las columnas llenas con los valores de una matriz asociativa y completamente segura para inyección SQL:

function insert($table, $record) { $cols = array(); $vals = array(); foreach (array_keys($record) as $col) $cols[] = sprintf("`%s`", $col); foreach (array_values($record) as $val) $vals[] = sprintf("''%s''", mysql_real_escape_string($val)); mysql_query(sprintf("INSERT INTO `%s`(%s) VALUES(%s)", $table, implode(", ", $cols), implode(", ", $vals))); } // Use as follows: insert("customer", array("customer_id" => 15, "qty" => 86));