Mysql
 sql >> Database >  >> RDS >> Mysql

È possibile utilizzare il risultato di una funzione SQL come campo in Doctrine?

Puoi mappare un risultato di una singola colonna in un campo di entità - guarda le query native e ResultSetMapping Per realizzare questo. Come semplice esempio:

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();

Quindi nella tua entità Prodotto avresti un $reviewsCount campo e il conteggio verrebbe mappato su quello. Nota che funzionerà solo se hai una colonna definita nei metadati di Doctrine, in questo modo:

/**
 * @ORM\Column(type="integer")
 */
private $reviewsCount;

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

Questo è quanto suggerito da Campi aggregati Documentazione dottrinale. Il problema è che stai essenzialmente facendo credere a Doctrine di avere un'altra colonna nel tuo database chiamata reviews_count , che è quello che non vuoi. Quindi, funzionerà comunque senza aggiungere fisicamente quella colonna, ma se mai esegui un doctrine:schema:update aggiungerà quella colonna per te. Sfortunatamente Doctrine non consente realmente le proprietà virtuali, quindi un'altra soluzione sarebbe quella di scrivere il tuo idratante personalizzato, o magari iscriverti a loadClassMetadata evento e aggiungi manualmente la mappatura dopo il caricamento della tua entità (o entità) particolare.

Tieni presente che se fai qualcosa come COUNT(r.id) AS reviewsCount allora non potrai più utilizzare COUNT(id) nel tuo addFieldResult() funzione e deve invece utilizzare l'alias reviewsCount per quel secondo parametro.

Puoi anche utilizzare ResultSetMappingBuilder come inizio nell'utilizzo della mappatura del set di risultati.

Il mio vero suggerimento è di farlo manualmente invece di passare attraverso tutte quelle cose extra. In sostanza, crea una query normale che restituisca sia la tua entità che i risultati scalari in un array, quindi imposta il risultato scalare su un campo corrispondente e non mappato sulla tua entità e restituisci l'entità.