Как я могу получить сумму полей связанного объекта? Например, Invoice и Bill имеют отношения OneToMany и ManyToOne соответственно, то есть Invoice может иметь много счетов. Сущность Bill имеет столбец Amount. Как счет-фактура может получить СУММУ соответствующей суммы счетов?
Лучший способ получить СУММУ поля связанного объекта в Doctrine 2?
Ответы (3)
Вы просите «лучший способ», но неясно, какой метод вы используете сейчас?
Если вам не нужно оптимизировать, у меня будет метод в вашем классе объектов Invoice, например:
public function getTotal(){
$total = 0;
foreach($this->bills as $b){
$total += $b->amount;
}
return $total;
}
Он не особо оптимизирован, но красив и понятен.
Если вы решите, что вам нужно его оптимизировать, вы можете:
A) создайте некоторый класс обслуживания, который знает о entitymanager, у которого есть метод, такой как getInvoiceTotal(Entity\Invoice $invoice), который выполняет запрос DQL для извлечения SUM() из базы данных
or
B) Сохраняйте промежуточный итог как свойство счета-фактуры. Используйте обратные вызовы жизненного цикла для обновления суммы счета-фактуры при добавлении/удалении/обновлении счетов.
На странице Doctrine Сводные поля описывается мало возможных решений этой проблемы. Они похожи на то, что описал @timdev, но предоставляют больше деталей реализации и указывают на предостережения каждого из них.
public function getTotal(){
$total = 0;
foreach($this->bills as $b){
$total += $b->amount;
}
return $total;
}
Лично мне не нравится вышеуказанное решение и доктрина агрегированное поле и подходит/оптимизируется, если вы ищете одну запись. Если вам нужно агрегировать несколько записей, как показано ниже:
|---invoice_id----|---bill total---|
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
это позволит получить все связанные счета для соответствующих счетов-фактур. Таким образом, для n записей счетов-фактур будут получены все связанные счета-фактуры для каждого счета-фактуры, что повредит оптимизации.
Для такой ситуации я сделал что-то вроде этого:
<?php
class InvoiceDTO
{
public function __construct($id, $total)
{
// Bind values to the object properties.
$this->invoiceId=$id;
$this->total= $total;
}
}
$query = $em->createQuery('SELECT NEW InvoiceDTO(i.id,SUM(b.amount)) FROM Invoice i JOIN i.bill b GROUP BY i');
$users = $query->getResult(); // array of InvoiceDTO
С этим решением будет выполнен только один запрос.