Doctrine2 нативные запросы

Лично мне известно 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
            ');

Источники: 1 - 2


13.04.2016 07:06