Необязательный LIMIT для функции, захватывающей все сообщения с PDO

Я пытаюсь создать функцию, которая захватит все сообщения в таблице. Я также хотел добавить необязательный параметр LIMIT. Вот пример:

function get_all_posts($conn, $limit = 0) {
if ($limit > 0) {
    $stmt = $conn->prepare("SELECT * FROM posts LIMIT :limit");
    $stmt->execute(array(
        ':limit' => $limit
    ));
    $results = $stmt->fetchAll();
    return $results ? $results : false ;
} else {
    $stmt = $conn->prepare("SELECT * FROM posts");
    $stmt->execute();
    $results = $stmt->fetchAll();
    return $results ? $results : false ;
}
}

Если я вызываю функцию без использования параметра limit, она работает и отображает все сообщения. Но если я вызову функцию следующим образом: get_all_posts($conn, "1"); Затем я получаю эту ошибку:

Неустранимая ошибка: необработанное исключение «PDOException» с сообщением «SQLSTATE [42000]: синтаксическая ошибка или нарушение прав доступа: 1064. У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с «1» в строке 1 в /Applications/MAMP/htdocs/sandbox/blog2/functions.php:19 Трассировка стека: #0/Applications /MAMP/htdocs/sandbox/blog2/functions.php(19): PDOStatement->execute(Array) #1 /Applications/MAMP/htdocs/sandbox/blog2/index.php(12): get_all_posts(Object(PDO), '1') #2 {main} добавлено в /Applications/MAMP/htdocs/sandbox/blog2/functions.php в строке 19

Может ли кто-нибудь показать мне, где я ошибся?


person Ben    schedule 06.11.2012    source источник


Ответы (4)


По умолчанию PDO execute() обрабатывает параметры как строку. Таким образом, он цитирует "1". Вам нужно будет использовать bindParam().

Хотя MySQL может справиться с этим, вы должны привязать этот параметр соответствующим образом (как INT). См. этот связанный вопрос для более подробной информации.

person Jason McCreary    schedule 06.11.2012
comment
Вы спасаете жизнь, спасибо! Вы говорите, что MySQL может справиться с этим, но в моем случае это не означает, что в некоторых случаях это будет работать, а в некоторых нет? - person Ben; 07.11.2012
comment
MySQL иногда снисходительно относится к сравнению строки с целым числом в зависимости от нашей конфигурации. В любом случае, я думаю, что в этом случае лучше связать limit как целое число. Похоже, hakre предоставил пример кода. - person Jason McCreary; 07.11.2012

1 не является строкой, поэтому не заключайте его здесь в кавычки: get_all_posts($conn, 1);

person Sammitch    schedule 06.11.2012

Как сказал Саммитч, это потому, что это строка, а не целое число. Используйте это, чтобы исправить:

if (is_numeric($limit)) {
    $limit = (int)$limit;
    ... 

чтобы устранить любые проблемы с типом переменной

person topherg    schedule 06.11.2012
comment
На самом деле нет причин проверять, является ли он числовым. - person zerkms; 07.11.2012
comment
@zerkms Я всегда заранее гарантирую, что то, что я конвертирую в целое число, является числом на тот случай, если будет введено что-то, кроме числа (даже в строке), чтобы остановить ошибочную операцию, но для этого (int)'alskdfj' все равно будет равно 0 - person topherg; 07.11.2012
comment
@cgoddard: аргумент для LIMIT должен ВСЕГДА быть числом. Так что нет смысла его проверять вообще. но для этого (int)'alskdfj' все равно будет равно 0 --- и что? - person zerkms; 07.11.2012
comment
@ user1801541 просто используйте (int)$limit, затем - person topherg; 07.11.2012
comment
Я пробовал: if ($limit › 0 && is_numeric($limit)) { и удалил кавычки вокруг вызова функции, но все равно получаю ту же ошибку. - person Ben; 07.11.2012
comment
@zerkms да, но в тех случаях, когда это не только для этого, просто то, чему меня учили для хорошей практики - person topherg; 07.11.2012

В предложении LIMIT вам нужен целочисленный параметр.

В вашем коде вы передаете :limit' parameter's value viaexecute`, которые являются строками.

Строка не является целым числом. Это несоответствие создает вашу проблему.

Вместо этого бинируйте параметр как целое число, и все в порядке.

$stmt = $conn->prepare("SELECT * FROM posts LIMIT :limit");
$stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
$success = $stmt->execute();
$results = $stmt->fetchAll();

Поскольку вы принимаете переменную $limit через параметр функции, вы также должны дезинфицировать ее значение:

$limit = (int) $limit;

Это гарантирует, что вы используете переменную типа integer при привязке ее в качестве целочисленного параметра.

person hakre    schedule 06.11.2012