Asked  7 Months ago    Answers:  5   Viewed   136 times

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('AppSupplier');
  }

  public function buyDetails()
  {
    return $this->hasMany('AppBuyDetail');
  }
}

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

 Answers

31

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'));
  }
}
Saturday, May 29, 2021
 
Jeff
answered 7 Months ago
70

Answer to Question 1:
You can use advance where clause when using eloquent orm like in your case, use can try:

Foo::whereHas('fooTypes', function($query){
    $query->whereTypeId(5);  
})->get();  

Answer to Question 2:

Data Mapper or Query builder is faster than ORM Active Record. So when you are writing very large applications with significant number of concurrent requests then Data Mapper / Query Builder is the way to go.

On the other hand ORM provides a much cleaner syntax and better code readability for someone who just started with Laravel or is writing small or medium size app where the number of concurrent requests will not be significantly large.

Query Builder syntax is nearer to the plain SQL queries, which anyone who has worked with databases and sql finds easy to relate to.
So its a choice you have to make depending your comfort with the Query builder syntax as well as the size of app you are writing.

Laravel Eloquent vs Fluent query builder

Saturday, May 29, 2021
 
MannfromReno
answered 7 Months ago
12

You would have to recursively get the children if you have an unknown depth like that.

Another option is to use the nested sets model instead of the adjacency list model. You can use something like baum/baum package for Laravel for nested sets.

"A nested set is a smart way to implement an ordered tree that allows for fast, non-recursive queries." - https://github.com/etrepat/baum

With this package you have methods like getDescendants to get all children and nested children and toHierarchy to get a complete tree hierarchy.

Wikipedia - Nested Set Model

Baum - Nested Set pattern for Laravel's Eloquent ORM

Managing Hierarchical Data in MySQL

Wednesday, June 23, 2021
 
Amber
answered 6 Months ago
73

Firstly you have to make your user_id field an index:

$table->index('user_id');

After that you can create a foreign key with an action on cascade:

$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

If you want to do that with a new migration, you have to remove the index and foreign key firstly and do everything from scratch.

On down() function you have to do this and then on up() do what I've wrote above:

$table->dropForeign('lists_user_id_foreign');
$table->dropIndex('lists_user_id_index');
$table->dropColumn('user_id');
Monday, August 2, 2021
 
Extrakun
answered 4 Months ago
11

You can use the package Laravel 5 Javascript Validation. This package enables transparent Javascript Valditaion in your views based on JQuery Validation Plugin

This is a basic example of how to reuse your validation rules in the controller.

PostController.php

namespace AppHttpControllers;

class PostController extends Controller {

    /**
     * Define your validation rules in a property in 
     * the controller to reuse the rules.
     */
    protected $validationRules=[
                'title' => 'required|unique|max:255',
                'body' => 'required'
    ];

    /**
     * Show the edit form for blog post
     * We create a JsValidator instance based on shared validation rules
     * @param  string  $post_id
     * @return Response
     */
    public function edit($post_id)
    {
        $validator = JsValidator::make($this->validationRules);
        $post = Post::find($post_id);

        return view('edit_post')->with([
            'validator' => $validator,
            'post' => $post
        ]);
    }

    /**
     * Store the incoming blog post.
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $v = Validator::make($request->all(), $this->validationRules]);

        if ($v->fails())
        {
            return redirect()->back()->withErrors($v->errors());
        }

        // do store stuff
    }
}

In the view you simply should print the validator object passed to the view. Remember that this package depends of JQuery and you have to include before that jsvalidation.js

edit_post.blade.php

 <div class="container">
     <div class="row">
         <div class="col-md-10 col-md-offset-1">
             <form class="form-horizontal" role="form" method="POST" action="" id="ddd">
                 <div class="form-group">
                     <label class="col-md-4 control-label">Title</label>
                     <div class="col-md-6">
                         <input type="text" class="form-control" name="title">
                     </div>
                 </div>
                 <div class="form-group">
                     <label class="col-md-4 control-label">Array</label>
                     <div class="col-md-6">
                         <textarea name="body"></textarea>
                     </div>
                 </div>
             </form>
         </div>
     </div>
 </div>
 <!-- Scripts -->
 <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
 <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>

 <!-- Laravel Javascript Validation -->
 <script type="text/javascript" src="{{ asset('vendor/jsvalidation/js/jsvalidation.js')}}"></script>
 {!! $validator !!}
Friday, August 13, 2021
 
Aniket Thakur
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share