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

É possível usar o resultado de uma função SQL como um campo no Doctrine?


Você pode mapear um resultado de coluna única para um campo de entidade - veja consultas nativas e Mapeamento do conjunto de resultados Para alcançar isto. Como um exemplo simples:
use Doctrine\ORM\Query\ResultSetMapping;

$sql = '
    SELECT p.*, COUNT(r.id)
    FROM products p
    LEFT JOIN reviews r ON p.id = r.product_id
';

$rsm = new ResultSetMapping;
$rsm->addEntityResult('AppBundle\Entity\Product', 'p');
$rsm->addFieldResult('p', 'COUNT(id)', 'reviewsCount');

$query   = $this->getEntityManager()->createNativeQuery($sql, $rsm);
$results = $query->getResult();

Então, em sua entidade Product, você teria um $reviewsCount campo e a contagem seria mapeada para isso. Observe que isso só funcionará se você tiver uma coluna definida nos metadados do Doctrine, assim:
/**
 * @ORM\Column(type="integer")
 */
private $reviewsCount;

public function getReviewsCount()
{
    return $this->reviewsCount;
}

Isto é o que é sugerido pelo Campos agregados Documentação da doutrina. O problema aqui é que você está essencialmente fazendo o Doctrine pensar que você tem outra coluna em seu banco de dados chamada reviews_count , que é o que você não quer. Portanto, isso ainda funcionará sem adicionar fisicamente essa coluna, mas se você executar um doctrine:schema:update ele vai adicionar essa coluna para você. Infelizmente o Doctrine não permite propriedades virtuais, então outra solução seria escrever seu próprio hidratante personalizado, ou talvez assinar o loadClassMetadata evento e adicione manualmente o mapeamento após o carregamento de sua entidade (ou entidades) específica.

Observe que, se você fizer algo como COUNT(r.id) AS reviewsCount então você não pode mais usar COUNT(id) em seu addFieldResult() função e deve usar o alias reviewsCount para esse segundo parâmetro.

Você também pode usar o ResultSetMappingBuilder como um começo para usar o mapeamento do conjunto de resultados.

Minha sugestão real é fazer isso manualmente em vez de passar por todas essas coisas extras. Essencialmente, crie uma consulta normal que retorne sua entidade e resultados escalares em uma matriz e, em seguida, defina o resultado escalar para um campo não mapeado correspondente em sua entidade e retorne a entidade.