Laravel Eloquent: Best Way to Calculate Total Price

25,179

Solution 1

This can be done in (at least) 2 ways.

Using pure Eloquent model logic:

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

The only issue here is that it needs to fetch all buy details from the database but this is something you need to fetch anyway to display details in the view.

If you wanted to avoid fetching the relation from the database you could build the query manually:

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

Solution 2

I realise an answer’s already been accepted, but just thought I’d add my own detailing another approach.

Personally, I like to put “aggregate” methods like these on custom collection classes. So if I have a Buy model that can have many BuyDetail models, then I would put a getTotal() method on my BuyDetailCollection method like this:

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

I can then add this to the BuyDetail model:

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

And use my getTotal() method where ever I need to now:

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

$total = $buy->buyDetails->getTotal();
Share:
25,179

Related videos on Youtube

Wendy Adi
Author by

Wendy Adi

Currently Engineering Manager at Pintu.co.id former: Software Architect/Engineering Manager at Shipper.id CoFounder of Angloo Technologies Principal Software Engineer at Tokopedia

Updated on July 09, 2022

Comments

  • Wendy Adi
    Wendy Adi almost 2 years

    Im building a simple buy and sell application with Laravel 5.1. Each Buy Model has many BuyDetail which stores bought item quantity and buy_price. I have implement the relationship between table on the Model.

    class Buy extends Model
    {
      #Eloquent relationships
    
      public function supplier()
      {
        return $this->belongsTo('App\Supplier');
      }
    
      public function buyDetails()
      {
        return $this->hasMany('App\BuyDetail');
      }
    }
    

    I'd like to calculate the total price for each Buy. What is the best way to calculate the total price using Eloquent ORM?

    for now i just implement it like this:

    @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
    
  • Wendy Adi
    Wendy Adi almost 9 years
    this is works :). Thanks. I prefer the 2nd approach, now i can just access it via $value->getTotalPrice(). note: too many closing branches on the 2nd code
  • Ben Claar
    Ben Claar almost 9 years
    Thanks for this -- I've thought about doing a custom collection before but didn't realize it was so easy.
  • Hardist
    Hardist over 8 years
    When I try to use this second approach, it gives me the following error: Call to a member function addEagerConstraints() on a non-object Any ideas why?
  • jedrzej.kurylo
    jedrzej.kurylo over 8 years
    Hae you defined the buyDetails() method? It should return the relation definition
  • Chaudhry Waqas
    Chaudhry Waqas over 8 years
    I have a problem in laravel please see if you can answer link
  • Martin Bean
    Martin Bean over 8 years
    @Adamnick Please don’t summon me to answer your questions.
  • Martin Bean
    Martin Bean over 8 years
    @Adamnick You specifically asked me to answer your question as though I were a performing monkey. I don’t appreciate that. I choose which questions I’ll answer.
  • Szabi Zsoldos
    Szabi Zsoldos almost 8 years
    Great one @Martin Bean