Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Ist es möglich, das Ergebnis einer SQL-Funktion als Feld in Doctrine zu verwenden?

Sie können einen Einzelspaltenergebnis in ein Entitätsfeld - siehe native Abfragen und ResultSetMapping um das zu erreichen. Als einfaches Beispiel:

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

Dann hätten Sie in Ihrer Produktentität einen $reviewsCount Feld und die Zählung würde darauf abgebildet werden. Beachten Sie, dass dies nur funktioniert, wenn Sie eine Spalte in den Doctrine-Metadaten definiert haben, etwa so:

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

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

Dies wird von vorgeschlagen Aggregierte Felder Lehrdokumentation. Das Problem ist hier, dass Sie Doctrine im Wesentlichen glauben machen, dass Sie eine weitere Spalte namens reviews_count in Ihrer Datenbank haben , was Sie nicht wollen. Dies funktioniert also immer noch, ohne diese Spalte physisch hinzuzufügen, aber wenn Sie jemals ein doctrine:schema:update ausführen Es wird diese Spalte für Sie hinzufügen. Leider erlaubt Doctrine nicht wirklich virtuelle Eigenschaften, also wäre eine andere Lösung, Ihren eigenen benutzerdefinierten Hydrator zu schreiben oder vielleicht loadClassMetadata zu abonnieren Ereignis und fügen Sie die Zuordnung nach dem Laden Ihrer bestimmten Entität (oder Entitäten) manuell hinzu.

Beachten Sie, dass, wenn Sie etwas wie COUNT(r.id) AS reviewsCount tun dann können Sie COUNT(id) nicht mehr verwenden in Ihrem addFieldResult() Funktion und muss stattdessen den Alias ​​reviewsCount verwenden für diesen zweiten Parameter.

Sie können auch den verwenden ResultSetMappingBuilder als Einstieg in die Verwendung des Resultset-Mappings.

Mein eigentlicher Vorschlag ist, dies manuell zu tun, anstatt all das zusätzliche Zeug durchzugehen. Erstellen Sie im Wesentlichen eine normale Abfrage, die sowohl Ihre Entität als auch skalare Ergebnisse in ein Array zurückgibt, setzen Sie dann das skalare Ergebnis auf ein entsprechendes, nicht zugeordnetes Feld in Ihrer Entität und geben Sie die Entität zurück.