Voici un aperçu de mon code:
$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);
Je reçois
Vous avez une erreur dans votre syntaxe SQL; vérifiez le manuel qui correspond à votre version de serveur MySQL pour la bonne syntaxe à utiliser près de '' 15 ', 15' à la ligne 1
Il semble que PDO ajoute des guillemets simples à mes variables dans la partie LIMIT du code SQL. Je l'ai recherché, j'ai trouvé ce bug qui, je pense, est lié: http://bugs.php.net/bug.php?id=44639
Est-ce ce que je regarde? Ce bug est ouvert depuis avril 2008! Que devons-nous faire en attendant?
J'ai besoin de créer une pagination et de m'assurer que les données sont propres, sécurisées pour l'injection SQL, avant d'envoyer l'instruction SQL.
Réponses:
Je me souviens avoir eu ce problème avant. Convertissez la valeur en entier avant de la transmettre à la fonction de liaison. Je pense que cela résout le problème.
la source
(int) trim($_GET['skip'])
, essayezintval(trim($_GET['skip']))
.La solution la plus simple serait de désactiver le mode d'émulation. Vous pouvez le faire en ajoutant simplement la ligne suivante
De plus, ce mode peut être défini comme paramètre de constructeur lors de la création d'une connexion PDO . Cela pourrait être une meilleure solution car certains rapportent que leur pilote ne prend pas en charge la
setAttribute()
fonction.Cela résoudra non seulement votre problème de liaison, mais vous permettra également d'envoyer des valeurs directement dans
execute()
, ce qui réduira considérablement votre code. En supposant que le mode d'émulation a déjà été défini, toute l'affaire prendra jusqu'à une demi-douzaine de lignes de codela source
SQLSTATE[IM001]: Driver does not support this function: This driver doesn't support setting attributes
... Pourquoi n'est-ce jamais si simple pour moi :) Bien que je sois sûr que cela attirera la plupart des gens, dans mon cas, j'ai fini par devoir utiliser quelque chose de similaire à la réponse acceptée. Juste un avertissement pour les futurs lecteurs!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
. C'est nouveau pour moi, mais là encore je ne fais que commencer avec l'AOP. J'utilise habituellement mysqli, mais j'ai pensé que j'essaierais d'élargir mes horizons.setAttribute
l'instruction ($ stm, $ stmt) pas pour l'objet pdo.En regardant le rapport de bogue, les éléments suivants pourraient fonctionner:
mais êtes-vous sûr que vos données entrantes sont correctes? Parce que dans le message d'erreur, il semble y avoir une seule citation après le nombre (par opposition au nombre entier entre guillemets). Cela peut également être une erreur avec vos données entrantes. Pouvez-vous faire un
print_r($_GET);
pour le savoir?la source
C'est juste comme résumé.
Il existe quatre options pour paramétrer les valeurs LIMIT / OFFSET:
Désactivez
PDO::ATTR_EMULATE_PREPARES
comme mentionné ci - dessus .Ce qui empêche les valeurs transmises par
->execute([...])
de toujours apparaître sous forme de chaînes.Passez au remplissage manuel des
->bindValue(..., ..., PDO::PARAM_INT)
paramètres.Ce qui est cependant moins pratique qu'une -> liste d'exécution [].
Faites simplement une exception ici et interpolez simplement des entiers simples lors de la préparation de la requête SQL.
Le casting est important. Plus couramment, vous voyez
->prepare(sprintf("SELECT ... LIMIT %d", $num))
utilisé à de telles fins.Si vous n'utilisez pas MySQL, mais par exemple SQLite ou Postgres; vous pouvez également convertir des paramètres liés directement dans SQL.
Encore une fois, MySQL / MariaDB ne prend pas en charge les expressions dans la clause LIMIT. Pas encore.
la source
{$_GET->int["limit"]}
pour de tels cas.pour
LIMIT :init, :end
Vous devez vous lier de cette façon. si vous aviez quelque chose comme
$req->execute(Array());
ça ne fonctionnera pas car il seraPDO::PARAM_STR
converti en toutes les variables du tableau et pour cela,LIMIT
vous avez absolument besoin d'un entier. bindValue ou BindParam comme vous le souhaitez.la source
Puisque personne n'a expliqué pourquoi cela se produit, j'ajoute une réponse. La raison pour laquelle il se comporte ainsi est que vous utilisez
trim()
. Si vous regardez le manuel PHP pourtrim
, le type de retour eststring
. Vous essayez alors de transmettre cela commePDO::PARAM_INT
. Voici quelques moyens de contourner ce problème:filter_var($integer, FILTER_VALIDATE_NUMBER_INT)
pour vous assurer que vous passez un entier.intval()
(int)
is_int()
Il existe de nombreuses autres façons, mais c'est essentiellement la cause principale.
la source
bindValue offset et limit en utilisant PDO :: PARAM_INT et cela fonctionnera
la source
// AVANT (Erreur présente) $ query = ".... LIMIT: p1, 30;"; ... $ stmt-> bindParam (': p1', $ limiteInferior);
// APRÈS (Erreur corrigée) $ query = ".... LIMIT: p1, 30;"; ... $ limiteInferior = (int) $ limiteInferior; $ stmt-> bindParam (': p1', $ limiteInferior, PDO :: PARAM_INT);
la source
PDO::ATTR_EMULATE_PREPARES
m'a donné leMa solution de contournement était de définir une
$limit
variable sous forme de chaîne, puis de la combiner dans l'instruction prepare comme dans l'exemple suivant:la source
Il se passe beaucoup de choses entre les différentes versions de PHP et les bizarreries de PDO. J'ai essayé 3 ou 4 méthodes ici mais je n'ai pas pu faire fonctionner LIMIT.
Ma suggestion est d'utiliser le formatage / concatination de chaîne AVEC un filtre intval () :
Il est très important d'utiliser intval () pour empêcher l'injection SQL, en particulier si vous obtenez votre limite de $ _GET ou autre. Si vous faites cela, c'est le moyen le plus simple de faire fonctionner LIMIT.
On parle beaucoup du «problème avec LIMIT dans PDO» mais ma pensée ici est que les paramètres PDO n'ont jamais été utilisés pour LIMIT car ils seront toujours des entiers et un filtre rapide fonctionne. Pourtant, c'est un peu trompeur car la philosophie a toujours été de ne pas faire de filtrage d'injection SQL soi-même, mais plutôt de «faire en sorte que PDO le gère».
la source