Вопрос по mysql, php – Как я могу передать массив параметров PDO, но все же указать их типы?

18
$sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%')
LIMIT :limit1, :limit2";

Я хочу по-прежнему использовать вход массива следующим образом:

$stmt->execute($array);

В противном случае я не могу использовать один и тот же метод для выполнения моих запросов.

В то же время: limit1 и: limit2 не будут работать, если они не вставлены следующим образом:

$stmt->bindParam(':limit1', $limit1, PDO::PARAM_INT);

Я пытался сделать оба, но он не выполняется с bindParams:

$stmt->bindParam(':limit2', $limit2, PDO::PARAM_INT);
$stmt->execute($array);

Как обойти это?

Я подумал, что смогу расширить PDOStatement и добавить новый метод "bindLimit". или что-то еще, но я не могу понять, какой внутренний метод PDO использует для привязки параметров к переменной.

@webbiedave - это просто удобный метод для подготовки, связывания и выполнения с необязательными аргументами для предельных переменных. Я мог бы просто добавить строку «LIMIT n, n»; до конца $ sql, но тогда мне придется использовать регулярное выражение для очистки входной строки. user1275136
& quot; В противном случае я не могу использовать один и тот же метод для выполнения моих запросов. & quot; Можете ли вы объяснить больше об этом методе? webbiedave
+1 за идею расширения PDOStatement (однако я не уверен, что это решение). hakre
Можете ли вы проверить предельные параметры и связать их явно, если они есть, но в противном случае просто используйте execute? user1086498

Ваш Ответ

3   ответа
18

PDO::ATTR_EMULATE_PREPARESтогда это будет работать. Я только что узнал, что этот параметр включен по умолчанию для mysql, что означает, что вы фактически никогда не используете подготовленные операторы, php создает для вас динамический sql, цитирует значения для вас и заменяет заполнители. Я, главный невнятный

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $pdo->prepare($sql);
$stmt->execute(array(5)); //works!

Приготовления эмулируются по умолчанию из соображений производительности.

Смотри такжеPDO MySQL: Use PDO::ATTR_EMULATE_PREPARES or not?

да смеется проверьте журнал запросов MySQL до и после отключения этого параметра, и вы увидите, что вы действительно никогда не использовали подготовленные операторы за все эти годы.
Я должен согласиться с Eggyal: WTF? Это самая странная вещь, о которой я когда-либо слышал.
8

PDOStatement::execute:

input_parameters

An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as PDO::PARAM_STR.

По большей части это остается совершенно незамеченным, поскольку MySQLнеявное преобразование типов обрабатывает остальное (но это может вызвать нежелательное поведение, если MySQL использует особенно странный набор символов соединения, поскольку преобразование строк чисел обратно в их числовое значение может не дать ожидаемого результата).

В вашем случае MySQL пытается выполнитьLIMIT предложение, которое имеет строковые аргументы. Пока этоcould попытаться решить это, используя неявное преобразование типов, как это происходит везде, где появляется строка там, где должно быть целое число,это просто не беспокоит и убегает плакать вместо этого.

Итак, вам нужно сообщить PDO, что эти конкретные параметры являются целыми числами. Поскольку даже PHP не знает, к какому типу относятся его переменные, я считаю, что единственный способ сделать это - напрямую связать их сPDOStatement::bindParam или жеPDOStatement::bindValue как вы делаете (хотя это не такstrictly необходимо указать$data_type аргумент как простой(int) актерский состав$variable дает в противном случае достаточно непонятную систему типов PHP).

Что касается внутреннего метода, который использует PDO для привязки параметров к переменной, взгляните наreally_register_bound_param() (неудивительно, что не знаком с PHP, поэтому вам будет очень весело в C).

Удачи!

0

когда они не являются пользовательским вводом?

$start = 0;
$limit = 20;
$sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%')
    LIMIT $start, $limit";

Даже если$start а также$limit определяются из пользовательского ввода, скажем, из$_GETВы можете проверить значение сis_int().

@YourCommonSense Как получить инъекционную атаку от целого числа? Ответ. Вы не можете
@YourCommonSense Я хотел бы знать, почему вы отклонили мой пост. Не могли бы вы объяснить?
@YourCommonSense не хочет объясниться?

Похожие вопросы