Лучший способ получить СУММУ поля связанного объекта в Doctrine 2?

#doctrine-orm

#doctrine-orm

Вопрос:

Как я могу получить сумму полей связанного объекта? Например, Invoice и Bill имеют отношение OneToMany и ManyToOne соответственно, то есть в счете может быть много счетов. Объект Bill имеет столбец суммы. Как счет может получить сумму связанных с ним счетов?

Ответ №1:

Вы просите «лучший способ», но неясно, какой метод вы используете сейчас?

Если вам не нужно оптимизировать, у меня просто был бы метод в вашем классе объектов Invoice, например:

 public function getTotal(){
    $total = 0;
    foreach($this->bills as $b){
        $total  = $b->amount;
    } 
    return $total;
}
  

Это не особенно оптимизировано, но красиво и понятно.

Если вы решите, что вам нужно оптимизировать его, вы могли бы:

A) создайте некоторый класс обслуживания, который знает о entitymanager, у которого есть метод, подобный getInvoiceTotal (Entity Invoice $ invoice), который выполняет запрос DQL для извлечения SUM () из базы данных

или

Б) Сохраните текущую сумму как свойство Invoice. Используйте обратные вызовы жизненного цикла для обновления итоговой суммы счета при добавлении / удалении / обновлении счетов.

Ответ №2:

На странице Aggregate Fields Doctrine описаны несколько возможных решений этой проблемы. Они похожи на то, что описал @timdev, но предоставляют более подробную информацию о реализации и указывают на предостережения каждого.

Ответ №3:

 public function getTotal(){
$total = 0;
foreach($this->bills as $b){
    $total  = $b->amount;
} 
return $total;
}
  

Лично мне не нравится вышеупомянутое решение и решение для агрегированного поля doctrine, и оно подходит / оптимизировано, если вы ищете единственную запись.
Если вам нужно объединить несколько записей, как показано ниже:

 |---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
  

С этим решением будет выполнен только один запрос.