PDO подготовил оператор IN в выражении с именными заполнителями не работает должным образом

Скажем по сценарию: $ids = 2,3, Но по какой-то причине записи возвращаются, как если бы: $ids = 2,

Я считаю, что в этой строке есть какая-то проблема из полного кода, потому что, когда я эхо $ids, это возвращает 2,3, но фактический запрос возвращается, как будто есть только один идентификатор. То есть он возвращает события только из одного курса (с идентификатором 2).

$statement->execute(array("ids" => $ids, 'timestart' => $timestart, 'timeend' => $timeend))) {

мой полный код:

$ids = array_map(function($item) { return $item->id; }, $entitlementsVOs);
$ids = implode(', ', $ids); //echo shows 2,3

$timestart = isset($_GET['start']) && $_GET['start'] != "" ? $_GET['start'] : null;
$timeend = isset($_GET['end']) && $_GET['end'] != "" ? $_GET['end'] : null;

$statement = $this->connection->prepare("SELECT name AS title, timestart AS start, timestart + timeduration AS end FROM event WHERE courseid IN(:ids) AND timestart >= :timestart AND timestart + timeduration <= :timeend");
$statement->setFetchMode(\PDO::FETCH_CLASS, get_class(new EventVO()));if($statement->execute(array("ids" => $ids, 'timestart' => $timestart, 'timeend' => $timeend))) {
return $statement->fetchAll();
} else {
return null;
}

постскриптум ручной запуск этого запроса в mysql workbench возвращает мои две записи (1 из идентификатора курса 2, а другую из курса 3), где я заменяю в операторе (2,3), но при выполнении php я получаю только одну запись назад.

Если я жестко закодирую значения в php courseid IN(2,3)Например:

$statement = $this->connection->prepare("SELECT name AS title, timestart AS start, timestart + timeduration AS end FROM event WHERE courseid IN(2,3) AND timestart >= :timestart AND timestart + timeduration <= :timeend");

Я получаю то, что ожидаю, поэтому я считаю, что есть какая-то проблема с implode, или же IN оператор или $statement->execute,

Редактировать:

Я читал обман, но я не знаю, с чего начать с именных заполнителей, чтобы добиться того же. Мой вопрос: когда у меня есть оба именованных параметра и оператор IN, оператор dupe использует оператор IN только с местозаполнителями.

Редактировать 2

Я прочитал второй обман, это не связано, мой вопрос использует сочетание IN и именованных заполнителей, связанный вопрос не решает эту проблему, однако, у меня есть решение в ответе.

2

Решение

Это должно работать для вас:

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

Здесь я создаю первый массив $ids который содержит только простые идентификаторы, например,

[2, 3]

Затем я также создал массив $preparedIds который содержит заполнители как массив, который вы потом используете в подготовленном выражении. Этот массив выглядит примерно так:

[":id2", ":id3"]

И я также создаю массив под названием $preparedValues который держит $preparedIds в качестве ключей и $ids в качестве значений, которые вы потом сможете использовать для execute() вызов. Массив выглядит примерно так:

[":id2" => 2, ":id3" => 3]

После этого вам хорошо идти. В подготовленном заявлении я просто implode() $preparedIds массив, так что оператор SQL выглядит примерно так:

... IN(:id2,:id3) ...

И тогда вы можете просто execute() Ваш запрос. Там я просто array_merge() ваш $preparedValues массив с другим массивом заполнителей.

<?php

$ids = array_map(function($item){
return $item->id;
}, $entitlementsVOs);

$preparedIds = array_map(function($v){
return ":id$v";
}, $ids);

$preparedValues = array_combine($preparedIds, $ids);$timestart = (!empty($_GET['start']) ? $_GET['start'] : NULL );
$timeend = (!empty($_GET['end']) ? $_GET['end'] : NULL );$statement = $this->connection->prepare("SELECT name AS title, timestart AS start, timestart + timeduration AS end FROM event WHERE courseid IN(" . implode(",", $preparedIds) . ") AND timestart >= :timestart AND timestart + timeduration <= :timeend");
$statement->setFetchMode(\PDO::FETCH_CLASS, get_class(new EventVO()));

if($statement->execute(array_merge($preparedValues, ["timestart" => $timestart, "timeend" => $timeend]))) {
return $statement->fetchAll();
} else {
return null;
}

?>

Также я думаю, что вы хотите поместить оператор if вокруг вашего запроса, так как ваш запрос не будет выполняться, если значения $timestart а также $timeend NULL.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]