Laravel Eloquent: лучший способ расчета общей цены

Я создаю простую заявку на покупку и продажу с Laravel 5.1. Каждая модель покупки имеет много BuyDetail, в котором хранится купленное количество товаров и buy_price. Я реализую связь между таблицей на модели.

class Buy extends Model
{
  #Eloquent relationships

  public function supplier()
  {
    return $this->belongsTo('App\Supplier');
  }

  public function buyDetails()
  {
    return $this->hasMany('App\BuyDetail');
  }
}

Я бы хотел рассчитать общую стоимость каждой покупки. Каков наилучший способ рассчитать общую стоимость с помощью Eloquent ORM?

теперь я просто реализую его следующим образом:

@foreach($buys as $key => $value)
    <?php
        $total = 0;
    ?>
    @foreach($value->buyDetails as $k => $bD)
        <?php
            $total += ($bD['buy_price']*$bD['qty']);
    ?>
    @endforeach

   <tr>
    <td>{{$value->ref_number}}</td>
    <td>{{$value->suplier->name}}</td>
    <td>{{$value->created_at}}</td>
    <td>{{$value->buyDetails->count()}}</td>
    <td>{{$total}}</td>
    <td>
        <a href="" class="btn btn-default btn-sm" title="show">Detail</a>
        <a href="" class="btn btn-primary btn-sm" title="edit">Edit</a>
        <a href="" class="btn btn-danger btn-sm" title="delete">Delete</a>
    </td>
  </tr>
@endforeach

Ответ 1

Это может быть сделано (по крайней мере) двумя способами.

Использование чистой логики модели Eloquent:

class Buy extends Model
{
  public function getTotalPrice() {
    return $this->buyDetails->sum(function($buyDetail) {
      return $buyDetail->quantity * $buyDetail->price;
    });
  }
}

Единственная проблема заключается в том, что ему нужно получить все данные о покупке из базы данных, но это то, что вам нужно, чтобы отобразить детали в представлении.

Если вы хотите избежать выборки из базы данных, вы можете создать запрос вручную:

class Buy extends Model
{
  public function getTotalPrice() {
    return $this->buyDetails()->sum(DB::raw('quantity * price'));
  }
}

Ответ 2

Я понимаю, что ответы уже приняты, но просто подумал, что Id добавляет мою собственную детальную информацию о другом подходе.

Лично мне нравится ставить "совокупные" методы, подобные этим, в пользовательских классах коллекции. Поэтому, если у меня есть модель Buy, которая может иметь много моделей BuyDetail, тогда я бы поместил метод getTotal() в мой метод BuyDetailCollection следующим образом:

use Illuminate\Database\Eloquent\Collection as EloquentCollection;

class BuyDetailCollection extends EloquentCollection
{
    public function getTotal()
    {
        return $this->items->sum(function ($detail) {
            return $detail->price * $detail->quantity;
        });
    }
}

Затем я могу добавить это в модель BuyDetail:

class BuyDetail extends Model
{
    public function newCollection(array $models = [])
    {
        return new BuyDetailCollection($models);
    }
}

И используйте мой метод getTotal(), где мне нужно:

$buy = Buy::with('buyDetails')->find($id);

$total = $buy->buyDetails->getTotal();