Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

A cláusula IN de declarações preparadas pelo PDO com espaços reservados nomeados não funciona conforme o esperado


Isso deve funcionar para você:

Então, como já foi dito nos comentários, você precisa de um espaço reservado para cada valor que deseja vincular à cláusula IN.

Aqui eu crio primeiro o array $ids que contém apenas os IDs simples, por exemplo.
[2, 3]

Então eu também criei o array $preparedIds que contém os espaços reservados como matriz, que você usa posteriormente na instrução preparada. Essa matriz se parece com isso:
[":id2", ":id3"]

E também crio um array chamado $preparedValues que contém o $preparedIds como chaves e $ids como valores, que você pode usar mais tarde para o execute() ligar. A matriz se parece com isso:
[":id2" => 2, ":id3" => 3]

Depois disso você está pronto para ir. Na instrução preparada eu apenas implode() os $preparedIds array, para que a instrução SQL se pareça com isto:
... IN(:id2,:id3) ...

E então você pode simplesmente execute() Sua pergunta. Lá eu apenas array_merge() seus $preparedValues array com o array de outros placeholders.
<?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;
    }

?>

Também acho que você deseja colocar uma instrução if em torno de sua consulta, pois sua consulta não será executada se os valores de $timestart e $timeend são NULOS.