Вот снимок моего кода:
$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', 15 'в строке 1
Кажется, что PDO добавляет одинарные кавычки к моим переменным в части LIMIT кода SQL. Я посмотрел, я нашел эту ошибку, которая, как мне кажется, связана: http://bugs.php.net/bug.php?id=44639
Это то, на что я смотрю? Эта ошибка обнаружена с апреля 2008 года! Что нам пока что делать?
Мне нужно создать некоторую разбивку на страницы и убедиться, что данные чистые, безопасные для SQL-инъекций, перед отправкой оператора sql.
Ответы:
Я помню, как раньше у меня была эта проблема. Преобразуйте значение в целое число, прежде чем передать его функции привязки. Думаю, это решает проблему.
источник
(int) trim($_GET['skip'])
, чтобы попробоватьintval(trim($_GET['skip']))
.Самым простым решением было бы выключить режим эмуляции. Вы можете сделать это, просто добавив следующую строку
Также этот режим может быть установлен как параметр конструктора при создании соединения PDO . Это могло быть лучшим решением, поскольку некоторые сообщают, что их драйвер не поддерживает эту
setAttribute()
функцию.Это не только решит вашу проблему с привязкой, но также позволит вам отправлять значения напрямую
execute()
, что значительно сделает ваш код короче. Если предположить, что режим эмуляции уже установлен, все это займет около полдюжины строк кода.источник
SQLSTATE[IM001]: Driver does not support this function: This driver doesn't support setting attributes
... Почему для меня это никогда не бывает так просто :) Хотя я уверен, что это поможет большинству людей, в моем случае мне пришлось использовать что-то похожее на принятый ответ. Внимание будущим читателям!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
. Для меня это ново, но опять же, я только начинаю работать с PDO. Обычно использую mysqli, но решил, что попытаюсь расширить свой кругозор.setAttribute
инструкцию ($ stm, $ stmt) не для объекта pdo.Глядя на отчет об ошибке, может сработать следующее:
но уверены ли вы, что ваши входящие данные верны? Поскольку в сообщении об ошибке, кажется, есть только одна кавычка после числа (в отличие от всего числа, заключенного в кавычки). Это также может быть ошибкой ваших входящих данных. Вы можете сделать это,
print_r($_GET);
чтобы узнать?источник
Это просто резюме.
Есть четыре варианта параметризации значений LIMIT / OFFSET:
Отключите,
PDO::ATTR_EMULATE_PREPARES
как указано выше .Это не позволяет значениям, передаваемым per,
->execute([...])
всегда отображаться в виде строк.Переключитесь на ручное заполнение
->bindValue(..., ..., PDO::PARAM_INT)
параметров.Что, однако, менее удобно, чем -> выполнить список [].
Просто сделайте здесь исключение и просто интерполируйте простые целые числа при подготовке SQL-запроса.
Кастинг важен. Чаще всего
->prepare(sprintf("SELECT ... LIMIT %d", $num))
используется для таких целей.Если вы не используете MySQL, но, например, SQLite или Postgres; вы также можете приводить связанные параметры непосредственно в SQL.
Опять же, MySQL / MariaDB не поддерживает выражения в предложении LIMIT. Еще нет.
источник
{$_GET->int["limit"]}
для таких случаев.для
LIMIT :init, :end
Вам нужно так привязать. если у вас было что-то подобное,
$req->execute(Array());
это не сработает, так как оно будетPDO::PARAM_STR
применяться ко всем варам в массиве, иLIMIT
вам абсолютно необходимо целое число. bindValue или BindParam, как хотите.источник
Поскольку никто не объяснил, почему это происходит, я добавляю ответ. Причина этого в том, что вы используете
trim()
. Если вы посмотрите руководство по PHP дляtrim
, тип возврата -string
. Затем вы пытаетесь передать это какPDO::PARAM_INT
. Вот несколько способов обойти это:filter_var($integer, FILTER_VALIDATE_NUMBER_INT)
чтобы убедиться, что вы передаете целое число.intval()
(int)
is_int()
Есть еще много способов, но это основная причина.
источник
bindValue смещение и ограничение с использованием PDO :: PARAM_INT, и он будет работать
источник
// ДО (Текущая ошибка) $ query = ".... LIMIT: p1, 30;"; ... $ stmt-> bindParam (': p1', $ limiteInferior);
// ПОСЛЕ (ошибка исправлена) $ query = ".... LIMIT: p1, 30;"; ... $ limiteInferior = (int) $ limiteInferior; $ stmt-> bindParam (': p1', $ limiteInferior, PDO :: PARAM_INT);
источник
PDO::ATTR_EMULATE_PREPARES
дал мнеМое обходное решение заключалось в том, чтобы задать
$limit
переменную как строку, а затем объединить ее в операторе подготовки, как в следующем примере:источник
Многое происходит между различными версиями PHP и странностями PDO. Я попробовал 3 или 4 метода здесь, но не смог заставить работать LIMIT.
Я предлагаю использовать форматирование / объединение строк с фильтром intval () :
Очень важно использовать intval () для предотвращения SQL-инъекции, особенно если вы получаете свой лимит от $ _GET и т.п. Если вы сделаете это, это будет самый простой способ заставить LIMIT работать.
Существует много разговоров о «проблеме с LIMIT в PDO», но я считаю, что параметры PDO никогда не должны использоваться для LIMIT, поскольку они всегда будут целыми числами, и работает быстрый фильтр. Тем не менее, это немного вводит в заблуждение, поскольку философия всегда заключалась в том, чтобы не выполнять фильтрацию SQL-инъекций самостоятельно, а скорее «Попросить PDO обработать это».
источник