2012-05-03 13 views
17
$sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%') 
LIMIT :limit1, :limit2"; 

quiero seguir utilizando el array entrada como esta:¿Cómo puedo pasar una matriz de parámetros de PDO y aún así especificar sus tipos?

$stmt->execute($array); 

De lo contrario, no se puede volver a utilizar el mismo método para ejecutar mis consultas.

Al mismo tiempo, el: Limit1 y: limit2 no funciona a menos que se pone en este aspecto:

$stmt->bindParam(':limit1', $limit1, PDO::PARAM_INT); 

Traté de hacer ambas cosas, pero no se ejecuta con los bindParams:

$stmt->bindParam(':limit2', $limit2, PDO::PARAM_INT); 
$stmt->execute($array); 

¿Cuál es el camino a su alrededor?

Pensé que podía extender PDOStatement y agregar un nuevo método "bindLimit" o algo así, pero no puedo averiguar qué método interno utiliza PDO para enlazar parámetros a una variable.

+1

+1 para la idea de extender PDOStatement (sin embargo, no estoy seguro de si esa es la solución). – hakre

+0

¿No puedes verificar los parametros de límite y vincularlos explícitamente si están presentes, pero de lo contrario simplemente usar execute? –

+0

"De lo contrario, no puedo volver a utilizar el mismo método para ejecutar mis consultas". ¿Puedes explicar más sobre este método? – webbiedave

Respuesta

18

Si desactiva la configuración predeterminada de PDO::ATTR_EMULATE_PREPARES, entonces funcionará.Me acabo de enterar de que esa configuración está activada por defecto para mysql, lo que significa que en realidad nunca usa declaraciones preparadas, php internamente crea sql dinámico para usted, citando los valores para usted y reemplazando los marcadores de posición. Ya, un wtf importante.

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 
$stmt = $pdo->prepare($sql); 
$stmt->execute(array(5)); //works! 

Los prepares se emulan de forma predeterminada por motivos de rendimiento.

ver tan bien PDO MySQL: Use PDO::ATTR_EMULATE_PREPARES or not?

+0

yup lol. compruebe el registro de consultas de mysql antes y después de deshabilitar esa configuración y verá que en realidad nunca estuvo usando declaraciones preparadas después de todos estos años, lol. – goat

+0

Tengo que estar de acuerdo con eggyal: ¿WTF? Esa es la cosa más extraña de la que haya oído hablar. – RonLugge

8

Como se indica en la documentación de PDOStatement::execute:

input_parameters

está ejecutando Matriz de valores con tantos elementos como hay parámetros en la instrucción SQL atado. Todos los valores se tratan como PDO::PARAM_STR.

En su mayor parte, esto va completamente desapercibido como MySQL de implicit type conversion se encarga del resto (pero puede causar un comportamiento indeseable si MySQL está utilizando un juego de caracteres unión especialmente raro, como la conversión de cadenas de números de nuevo a su el valor numérico podría no dar el resultado esperado).

En su caso, MySQL está intentando ejecutar una cláusula LIMIT que tiene argumentos de cadena. Mientras que podría intentar resolverlo usando su conversión de tipo implícita, como lo hace en cualquier otro lugar, una cadena aparece donde debe estar un entero, it simply doesn't bother y se ejecuta llorando en su lugar.

Por lo tanto, debe decirle a PDO que estos parámetros en particular son enteros. Dado que incluso PHP no sabe de qué tipo son sus variables, creo que la única forma de hacerlo es vincularlas directamente con PDOStatement::bindParam o PDOStatement::bindValue mientras lo hace (aunque no es estrictamente necesario para especificar el argumento $data_type como un simple (int) elenco del $variable le da al sistema de PHP de otra manera desorientado suficiente para trabajar con).

En cuanto al método interno que utiliza el PDO para vincular los parámetros a una variable, échale un vistazo a really_register_bound_param() (como era de esperar no estuvo expuesto a PHP, entonces te divertirás mucho en C).

¡Buena suerte!

0

¿Por qué se unen valores límite cuando no están entrada del usuario?

$start = 0; 
$limit = 20; 
$sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%') 
    LIMIT $start, $limit"; 

Incluso si $start y $limit se determinan a partir de entrada del usuario, dicen desde una $_GET, puede probar el valor con is_int().

+0

@YourCommonSense cuidado de explicarte? – inorganik

+0

@YourCommonSense Me encantaría saber por qué votó mi publicación. ¿Puede usted explicar por favor? – inorganik

+3

@YourCommonSense ¿Cómo se puede obtener un ataque de inyección de un número entero? Respuesta: no puedes – inorganik

Cuestiones relacionadas