Доктрина-как привязать массив к SQL?
мой SQL выглядит примерно так:
$sql = "select * from user where id in (:userId) and status = :status";
$em = $this->getEntityManager();
$stmt = $em->getConnection()->prepare($sql);
$stmt->bindValue(':userId', $accounts, DoctrineDBALConnection::PARAM_INT_ARRAY);
$stmt->bindValue(':status', 'declined');
$stmt->execute();
$result = $stmt->fetchAll();
но он возвращает:
при выполнении (...)
С params [[1,2,3,4,5,6,7,8,11,12,13,14], "отклонено"]
Примечание: преобразование массива в строку
Я не могу потому что мой реальный SQL сложнее (ex. содержит присоединенные select, союзы и так далее)
3 ответов
вы не можете использовать подготовленные операторы с массивами просто потому, что sql сам не поддерживает массивы. И это настоящий позор. Где-то вдоль линии вам действительно нужно определить, содержат ли ваши данные, скажем, три элемента и испускают IN (?,?,?). Доктрина ORM entity manager делает это автоматически.
к счастью, DBAL вы охвачены. Вы просто не используете bind или prepare. В руководстве приведен пример: http://doctrine-orm.readthedocs.io/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion
в вашем случае это будет выглядеть примерно так:
$sql = "select * from user where id in (?) and status = ?";
$values = [$accounts,'declined'];
$types = [Connection::PARAM_INT_ARRAY, \PDO::PARAM_STR];
$stmt = $conn->executeQuery($sql,$values,$types);
$result = $stmt->fetchAll();
приведенный выше код не тестировался, но вы должны уловить идею. (Убедитесь, что вы use Doctrine\DBAL\Connection;
на Connection::PARAM_INT_ARRAY
)
если вы хотите придерживаться :param
синтаксис, где порядок не имеет значения, что вам нужно сделать немного дополнительной работы, но я покажу вам более простой способ для привязки параметров:
// store all your parameters in one array
$params = array(
':status' => 'declined'
);
// then, using your arbitrary array of id's ...
$array_of_ids = array(5, 6, 12, 14);
// ... we're going to build an array of corresponding parameter names
$id_params = array();
foreach ($array_of_ids as $i => $id) {
// generate a unique name for this parameter
$name = ":id_$i"; // ":id_0", ":id_1", etc.
// set the value
$params[$name] = $id;
// and keep track of the name
$id_params[] = $name;
}
// next prepare the parameter names for placement in the query string
$id_params = implode(',', $id_params); // ":id_0,:id_1,..."
$sql = "select * from user where id in ($id_params) and status = :status";
в этом случае мы в конечном итоге с:
"select * from user where id in (:id_0,:id_1,:id_2,:id_3) and status = :status"
// now prepare your statement like before...
$stmt = $em->getConnection()->prepare($sql);
// ...bind all the params in one go...
$stmt->execute($params);
// ...and get your results!
$result = $stmt->fetchAll();
этот подход также будет работать с массивом строк.
вам нужно обернуть их в массив
$stmt->bindValue(':userId', array($accounts), array(\Doctrine\DBAL\Connection::PARAM_INT_ARRAY));
редактировать
Я должен был более подробно. Вы не можете связать массив таким образом, не готовьте sql execute непосредственно как пример в документах.
$stmt = $conn->executeQuery('SELECT * FROM articles WHERE id IN (?)',
array(array(1, 2, 3, 4, 5, 6)),
array(\Doctrine\DBAL\Connection::PARAM_INT_ARRAY));
вы не можете связать массив значений в один подготовленный параметр оператора