Лично мне известно 3 способа делать нативные запросы в Doctrine.
1. Считаю его простым и самым правильным:
$result = $this->getEntityManager()->getConnection()->fetchAllAssociative(
'select * from product where id = :id',
[
'id' => $id,
]
);
или
$id = 1;
$stmt = $this->getDoctrine()->getEntityManager()->getConnection()
->prepare('select * from product where id = :id');
$stmt->bindValue('id', $id);
$stmt->execute();
$result = $stmt->fetchAll();
или
$resultDbal = $this->em->getConnection()->executeQuery(
'SELECT * FROM product WHERE id = :id',
array('id' => $id),
array('id' => \PDO::PARAM_INT)
);
$result = $resultDbal->fetchAssociative();
2. Однако, иногда хочется написать в запросе IN
$result = $this->em->getConnection()->executeQuery(
'SELECT * FROM product WHERE id IN (?)',
array(array(1, 2, 3)),
array(\Doctrine\DBAL\Connection::PARAM_INT_ARRAY)
->fetchAll();
* такой запрос не работает с именованными параметрами и как Вы видите, мы используем знак вопроса.
3. Поэтому, лично я предпочитаю использовать вариант, который в IN инжектит данные + мы применим именованные параметры:
$rsm = new ResultSetMapping;
$rsm->addIndexByScalar('id');
$rsm->addScalarResult('name', 'product_title');
$rsm->addScalarResult('products', 'products_count');
$result = $this->_em->createNativeQuery('
SELECT
p.id,
p.title as name,
COUNT(p.*) as products
FROM
product p
WHERE
p.id IN (:ids)
GROUP BY p.title', $rsm)
->setParameter('ids', [1,2,3])
->getResult();
Бывает необходимость, когда нужно забиндить не значение, а значение в строке, например:
$sql = "select * from rule as r where r.rule = 'bank_id === :id'";
$stmt = $pdo->prepare($sql);
$stmt->bindParam('id', $id, \PDO::PARAM_INT);
$stmt->execute();
$result = $stmt->fetchAll();
однако, базы данных возвращают ошибку (пример SQLSTATE[HY093]: Invalid parameter number: :id
), но можно обойти:
$sql = "select * from rule as r where r.rule = REPLACE('bank_id === :id', ':id', :id)";
Автоматический биндинг значений
$query = $this->getEntityManager()->createQuery('
SELECT
NEW App\Service\Sitemap\Model\LinkData(
s.code,
s.name,
s.url,
s.linksBoxTitle,
d.title,
d.path,
s.id,
IDENTITY(s.htmlSitemapParent)
)
FROM App\Entity\Sitemap\Document d
INNER JOIN d.scope s
WHERE
s.isEnabled = true
');