Laravel : load objects on many level

Viewed 216

I have the following tables :

orders : id, etc...

order_lines : id, order_id, product_id, etc...

products : id, name, etc...

Foreign keys are defined.

My Laravel Models are defined as :

class Order

 public function orderLine()
    {
        return $this->hasMany('App\OrderLine');
    }
class OrderLine

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

    public function product()
    {
        return $this->belongsTo('App\Product');
    }
class Product

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

I've tried many things, but nothing is working. Here is the best solution for me, but it's not working.

class OrderController

public function show($id)
    {
        $user = Auth::user();
        $order = Order::where('user_id', '=', $user->id)->with(['orderLine.product'])->findOrFail($id);
        return view('layouts/order/index', compact('order'));
    }

I struggle to display the following data in the view :

@foreach($order->orderLine as $key => $orderLine)
<tr>
    <td>{{$orderLine->product->name}}</td>
<tr>
@endforeach

Product object is not loaded. I want to display the product name in the above loop.

4 Answers

Try to do like this:

public function show($id)
    {
        $user = Auth::user();
        $order = Order::with(['orderLines', 'orderLines.product'])
                      ->where('user_id', '=', $user->id)
                      ->findOrFail($id);
        return view('layouts/order/index', compact('order'));
    }
class OrderLine

public function order()
    {
        return $this->belongsTo(\App\Order::class, 'order_id');
    }

    public function product()
    {
        return $this->belongsTo(\App\Product::class, 'product_id');
    }
class Order

 public function orderLines()
    {
        return $this->hasMany(\App\OrderLine::class);
    }

Change name of orderLine to orderLines because order has many orderLines.

And in your blade:

@foreach($order->orderLines as $orderLine)
<tr>
    <td>{{$orderLine['product']->title}}</td> 
<tr>
@endforeach

Hello Dezaley and welcome to StackOverflow! Let's investigate your problem. As far as I can see you are selecting the model in the wrong way. Let me help you:

$order = Order::where(['id' => $id, 'user_id' => $user->id])->with('orderLine.product')->firstOrFail();

The answer from mare96, who was very friendly to help me, is working. However, I found out someting.

You can implement as (mare96 solution)


public function show($id)
    {
        $user = Auth::user();
        $order = Order::with(['orderLines', 'orderLines.product'])
                      ->where('user_id', '=', $user->id)
                      ->findOrFail($id);
        return view('layouts/order/index', compact('order'));
    }

@foreach($order->orderLines as $orderLine)
<tr>
    <td>{{$orderLine['product']->title}}</td> 
<tr>
@endforeach

In the view, I don't like the array syntax "$orderLine['product']->title". The following solution without the array is also working.

Solution is below :


public function show($id)
    {
        $user = Auth::user();
        $order = Order::with('orderLines', 'orderLines.product')
                      ->where('user_id', '=', $user->id)
                      ->findOrFail($id);
        return view('layouts/order/index', compact('order'));
    }

@foreach($order->orderLines as $orderLine)
<tr>
    <td>{{$orderLine->product->title}}</td> 
<tr>
@endforeach

In fact, my issue was that product was defined to null in the model, so Product was always null in the view.


Class OrderLine extends Model {
     public $product = null

I remove line "public $product = null" and it's working as expected. Thanks to the people who helped me.

give it a try -

    @foreach($order as $ordr)
    <tr>
    <td>{{$ordr->product_id->name}}</td>
    <tr>
    @endforeach
Related