121 votes

PHP PDO bindValue dans la LIMITE de

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; consultez le manuel qui correspond à votre serveur MySQL version pour le droit de la syntaxe à utiliser près de "15', 15' à la ligne 1

Il semble que PDO est l'ajout de guillemets simples pour mes variables dans la LIMITE de la partie du code SQL. Je l'ai regardé, j'ai trouvé ce bug qui je pense est lié: http://bugs.php.net/bug.php?id=44639

C'est ce que je suis en train de regarder? Ce bug a été ouvert depuis avril 2008! Que sommes-nous censés faire en attendant?

j'ai besoin de construire une partie de la pagination, et devez vous assurer que les données sont propres, sql injection-sûr, avant l'envoi de l'instruction sql.

170voto

Stephen Curran Points 4168

Je me souviens avoir eu ce problème avant. Convertir la valeur d'un nombre entier, avant de la transmettre à la fonction de liaison. Je pense que cela elle n'en résout.

$fetchPictures->bindValue(':skip', (int) trim($_GET['skip']), PDO::PARAM_INT);

48voto

$PDO->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

est tout ce que vous devez

aussi, beaucoup plus courte peut être utilisée. Je ne comprends pas pourquoi les utilisateurs de PHP sont si enclins à long et venteux code.

$skip = (isset($_GET['skip'])):$_GET['skip']:0;
$sql  = "SELECT * FROM pictures WHERE album = ? ORDER BY id ASC LIMIT ?, ?";
$stm  = $PDO->prepare($sql);
$stm->execute(array($_GET['albumid'],$skip,$max));
$pictures = $stm->fetchAll(PDO::FETCH_ASSOC);

18voto

Pekka 웃 Points 249607

En regardant le rapport de bug, le suivant peut fonctionner:

$fetchPictures->bindValue(':albumId', (int)$_GET['albumid'], PDO::PARAM_INT);

$fetchPictures->bindValue(':skip', (int)trim($_GET['skip']), PDO::PARAM_INT);  

mais êtes-vous sûr que vos données entrantes est correcte? Parce que dans le message d'erreur, il semble y avoir seulement une citation d'après le nombre (par opposition au nombre entier d'être entourées de guillemets). Ce pourrait être aussi une erreur avec la réception de vos données. Pouvez-vous faire un print_r($_GET); trouver?

8voto

Nicolas Manzini Points 2205

pour LIMIT :init, :end

Vous devez lier de cette façon. si vous aviez quelque chose comme $req->execute(Array()); il l'habitude de travailler comme il jetait PDO::PARAM_STR de tous les revendeurs dans le tableau et pour l' LIMIT vous avez absolument besoin d'un nombre Entier. bindValue ou BindParam que vous le souhaitez.

$fetchPictures->bindValue(':albumId', (int)$_GET['albumid'], PDO::PARAM_INT);

-2voto

Sebas Points 10416

Je suis confronté au même problème, mais malheureusement faire partie d'un cadre de génération de requêtes à l'aide d' $statement->execute($query, $params) je ne pouvais pas utiliser la solution de contournement proposée ci-dessus.

Cependant, j'ai mis en place un générique expression régulière cochez cette option pour remplacer la limite params de la clause limit.

Avec $sQuery , par exemple:

SELECT `name` FROM `students` 
WHERE `school` LIKE :PARAM1 
LIMIT :PARAM2, :PARAM3

Avec $sParamVal avoir n'importe quel type de valeur que vous attendez pour passer comme argument,

Le script suivant appliquée à votre liste d'argument devrait fonctionner. Rappelez-vous, c'est générique dans mon cas et le nombre de paramètres dépend de la requête, de sorte qu'une boucle est traitée, dont cet extrait:

    if (preg_match("/LIMIT :PARAM" . $i . "\\b/", $sQuery) === 1) {
        $sQuery = preg_replace("/LIMIT :PARAM" . $i . "\\b/", "LIMIT " . intval($sParamVal), $sQuery);
    } else if (preg_match("/LIMIT :PARAM[\d]+,[ ]*:PARAM" . $i . "\\b/", $sQuery) === 1) {
        $sQuery = preg_replace("/(LIMIT :PARAM[\d]+,[ ]*)(:PARAM" . $i . ")\\b/", "\\1 " . intval($sParamVal), $sQuery);
    } else if (preg_match("/LIMIT [\d]+,[ ]*:PARAM" . $i . "\\b/", $sQuery) === 1) {
        $sQuery = preg_replace("/(LIMIT [\d]+,[ ]*)(:PARAM" . $i . ")\\b/", "\\1 " . intval($sParamVal), $sQuery);
    } else {
        $arr[":PARAM" . $i] = $sParamVal;
    }

... etc

$statement = $cn->prepare($sQuery);
$statement->execute($arr);

Elle prendra en charge:

  • LIMITE X
  • LIMIT X, Y

Si X ou Y ne sont pas de type entier (sql injection, erreur dans les paramètres), intval seront plus susceptibles de retourner la valeur 0, bien que cela dépend des caractères les plus à gauche de la chaîne.

J'espère qu'il va donner une autre alternative pour ceux qui sont bloqués la façon dont je l'ai été.

Cheers!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X