Aquí hay una instantánea de mi código:
$fetchPictures = $PDO->prepare("SELECT *
FROM pictures
WHERE album = :albumId
ORDER BY id ASC
LIMIT :skip, :max");
$fetchPictures->bindValue(':albumId', $_GET['albumid'], PDO::PARAM_INT);
if(isset($_GET['skip'])) {
$fetchPictures->bindValue(':skip', trim($_GET['skip']), PDO::PARAM_INT);
} else {
$fetchPictures->bindValue(':skip', 0, PDO::PARAM_INT);
}
$fetchPictures->bindValue(':max', $max, PDO::PARAM_INT);
$fetchPictures->execute() or die(print_r($fetchPictures->errorInfo()));
$pictures = $fetchPictures->fetchAll(PDO::FETCH_ASSOC);
yo obtengo
Tiene un error en su sintaxis SQL; Consulte el manual que corresponde a la versión de su servidor MySQL para conocer la sintaxis correcta para usar cerca de '' 15 ', 15' en la línea 1
Parece que PDO agrega comillas simples a mis variables en la parte LIMIT del código SQL. Lo busqué y encontré este error que creo que está relacionado: http://bugs.php.net/bug.php?id=44639
¿Es eso lo que estoy mirando? ¡Este error se ha abierto desde abril de 2008! ¿Qué se supone que debemos hacer mientras tanto?
Necesito crear algo de paginación, y necesito asegurarme de que los datos estén limpios, seguros para la inyección de sql, antes de enviar la declaración sql.
Respuestas:
Recuerdo haber tenido este problema antes. Convierta el valor en un número entero antes de pasarlo a la función de enlace. Creo que esto lo resuelve.
fuente
(int) trim($_GET['skip'])
intentarlointval(trim($_GET['skip']))
.La solución más sencilla sería desactivar el modo de emulación. Puedes hacerlo simplemente agregando la siguiente línea
Además, este modo se puede establecer como un parámetro de constructor al crear una conexión PDO . Podría ser una mejor solución ya que algunos informan que su controlador no es compatible con la
setAttribute()
función.No solo resolverá su problema con el enlace, sino que también le permitirá enviar valores directamente
execute()
, lo que hará que su código sea mucho más corto. Suponiendo que el modo de emulación ya se haya configurado, todo el asunto tomará hasta media docena de líneas de código.fuente
SQLSTATE[IM001]: Driver does not support this function: This driver doesn't support setting attributes
... ¿Por qué nunca es tan simple para mí :) Si bien estoy seguro de que esto hará que la mayoría de la gente esté allí, en mi caso terminé teniendo que usar algo similar a la respuesta aceptada. ¡Solo un aviso para futuros lectores!PDO::ATTR_EMULATE_PREPARES Enables or disables emulation of prepared statements. Some drivers do not support native prepared statements or have limited support for them
. Es nuevo para mí, pero nuevamente estoy comenzando con PDO. Por lo general, uso mysqli, pero pensé que intentaría ampliar mis horizontes.setAttribute
la declaración ($ stm, $ stmt) y no el objeto pdo.Mirando el informe de errores, lo siguiente podría funcionar:
pero ¿está seguro de que sus datos entrantes son correctos? Porque en el mensaje de error, parece haber solo una comilla después del número (en lugar de que el número entero esté entre comillas). Esto también podría ser un error con sus datos entrantes. ¿Puedes hacer algo
print_r($_GET);
para averiguarlo?fuente
Esto es solo un resumen.
Hay cuatro opciones para parametrizar valores LIMIT / OFFSET:
Desactivar
PDO::ATTR_EMULATE_PREPARES
como se mencionó anteriormente .Lo que evita que los valores pasados por
->execute([...])
se muestren siempre como cadenas.Cambiar a
->bindValue(..., ..., PDO::PARAM_INT)
población de parámetros manual .Sin embargo, es menos conveniente que una -> lista de ejecución [].
Simplemente haga una excepción aquí e interpole enteros sin formato cuando prepare la consulta SQL.
El casting es importante. Más comúnmente se ve
->prepare(sprintf("SELECT ... LIMIT %d", $num))
utilizado para tales fines.Si no está utilizando MySQL, pero, por ejemplo, SQLite o Postgres; también puede convertir parámetros enlazados directamente en SQL.
Nuevamente, MySQL / MariaDB no admite expresiones en la cláusula LIMIT. Aún no.
fuente
{$_GET->int["limit"]}
para tales casos.para
LIMIT :init, :end
Necesitas unirte de esa manera. si tiene algo así
$req->execute(Array());
, no funcionará, ya que se enviaráPDO::PARAM_STR
a todas las variables de la matriz y, para el,LIMIT
es absolutamente necesario un número entero. bindValue o BindParam como desee.fuente
Como nadie ha explicado por qué sucede esto, agrego una respuesta. La razón por la que se está comportando así es porque está usando
trim()
. Si consulta el manual de PHPtrim
, el tipo de retorno esstring
. Entonces estás intentando pasar esto comoPDO::PARAM_INT
. Algunas formas de evitar esto son:filter_var($integer, FILTER_VALIDATE_NUMBER_INT)
para asegurarse de que está pasando un número entero.intval()
(int)
is_int()
Hay muchas más formas, pero esta es básicamente la causa principal.
fuente
bindValue offset y limit usando PDO :: PARAM_INT y funcionará
fuente
// ANTES (Error presente) $ consulta = ".... LÍMITE: p1, 30;"; ... $ stmt-> bindParam (': p1', $ limiteInferior);
// DESPUÉS (Error corregido) $ consulta = ".... LÍMITE: p1, 30;"; ... $ limiteInferior = (int) $ limiteInferior; $ stmt-> bindParam (': p1', $ limiteInferior, PDO :: PARAM_INT);
fuente
PDO::ATTR_EMULATE_PREPARES
me dio elMi solución fue establecer una
$limit
variable como una cadena, luego combinarla en la declaración de preparación como en el siguiente ejemplo:fuente
Está sucediendo mucho entre las diferentes versiones de PHP y las rarezas de PDO. Probé 3 o 4 métodos aquí pero no pude hacer que LIMIT funcionara.
Mi sugerencia es usar formato de cadena / concatenación CON un filtro intval () :
Es muy importante usar intval () para evitar la inyección de SQL, particularmente si obtiene su límite de $ _GET o similar. Si lo hace, esta es la forma más fácil de hacer que LIMIT funcione.
Se habla mucho sobre 'El problema con LIMIT en PDO', pero mi pensamiento aquí es que los parámetros de PDO nunca se usaron para LIMIT, ya que siempre serán números enteros y un filtro rápido funciona. Aún así, es un poco engañoso, ya que la filosofía siempre ha sido no realizar ningún filtrado de inyección SQL usted mismo, sino más bien 'Hacer que PDO lo maneje'.
fuente