Web

Как применить метод bindValue в предложении SQL LIMIT?

Вот снимок моего кода:

$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);

 

Я получил:

У вас ошибка в синтаксисе SQL; проверьте руководство, соответствующее вашей версии сервера MySQL, чтобы найти правильный синтаксис для использования '15', в строке 1

 

Кажется, что PDO добавляет одинарные кавычки к моим переменным в части LIMIT кода SQL. 

Мне нужно создать разбивку на страницы и убедиться, что данные допустимы и безопасны для SQL-инъекций, перед вызовом операторов sql.

 

Ответ 1

Я помню, раньше у меня была эта проблема. Приведите значение к целому типу перед передачей его функции привязки. Я думаю, это решает проблему.

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

 

Ответ 2

Самым простым решением было бы выключить режим эмуляции. Вы можете сделать это, просто добавив следующую строку:

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

 

Также этот режим можно установить как параметр конструктора при создании соединения PDO. Это могло бы быть лучшим решением, поскольку некоторые поставщики сообщают, что их драйвер не поддерживает функцию setAttribute().

Это не только решит вашу проблему с привязкой, но также позволит вам отправлять значения напрямую, используя execute(), что значительно сократит ваш код. Если предположить, что режим эмуляции уже установлен, это займет несколько строк кода:

$skip  = isset($_GET['skip']) ? (int)trim($_GET['skip']) : 0;

$sql   = "SELECT * FROM pictures WHERE album = ? ORDER BY id LIMIT ?, ?";

$stmt  = $PDO->prepare($sql);

$stmt->execute([$_GET['albumid'], $skip, $max]);

$pictures = $stmt->fetchAll(PDO::FETCH_ASSOC);

 

Ответ 3

Глядя на отчет об ошибке, может, выполнить следующее:

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

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

 

Но уверены ли вы, что ваши входящие данные верны? Потому что в сообщении об ошибке, кажется, есть только одна кавычка после числа (в отличие от всего числа, заключенного в кавычки). Это также могло быть ошибкой с вашими входящими данными. Можно проверить это, вызвав print_r($_GET).

 

Ответ 4

Существует четыре варианта параметризации значений LIMIT/OFFSET:

  1. Отключите PDO::ATTR_EMULATE_PREPARES,как указано выше. Это не позволяет значениям, передаваемым per, ->execute([...]) всегда отображаться в виде строк.

  2. Переключитесь на ручное заполнение ->bindValue(..., ..., PDO::PARAM_INT) параметров. Что, однако, менее удобно, чем -> выполнить список [].

  3. Просто сделайте здесь исключение и интерполируйте простые целые числа при подготовке SQL-запроса.

 $limit = intval($limit);

 $s     = $pdo->prepare("SELECT * FROM tbl LIMIT {$limit}");

 

Приведение типов очень важно. Чаще всего ->prepare(sprintf("SELECT ... LIMIT %d", $num) ) используется для таких целей.

  1. Если вы не используете MySQL, но, например, SQLite или Postgres, вы также можете приводить связанные параметры непосредственно в SQL.

 SELECT * FROM tbl LIMIT (1 * :limit)

 

Опять же, MySQL/MariaDB не поддерживает выражения в предложении LIMIT.

Схожие статьи

Web

Как установить расширения для Chrome в Opera?

Web

Почему происходит «Неопределенная переменная/индекс/смещение» в PHP

Web

Есть ли способ обновить расширение через composer и обойти ошибку ограничения памяти в Magento2

Руководство для веб-мастера: meta property og title content
Web

Руководство для веб-мастера: meta property og title content

×