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

Как получить значения из выпадающего меню с помощью PHP

Самый быстрый DNS-сервер России: сравниваем и выбираем лучший из них
Web

Самый быстрый DNS-сервер России: сравниваем и выбираем лучший из них

Web

Как получить содержимое POST на php?

Web

Ошибка при открытии потока в PHP: отсутствует файл или каталог