Home > Blockchain >  Laravel eloquent for four tables
Laravel eloquent for four tables

Time:04-20

I'm new to Laravel. I am developing a project. and in this project I have 4 tables related to each other

-Users

-Orders

-OrderParcels

-Situations

When listing the parcels of an order, I want to get the information of that order only once, the user information of that order once again, and list the parcels as a table under it. so far everything ok. but I also want to display the status of the parcels listed in the table as names. I couldn't add the 4th table to the query. do you have a suggestion? I'm putting pictures that explain the structure below.

enter image description here

enter image description here

My current working code is

$orderParcels = Orders::whereId($id) 
        ->with('parcels')
        ->with('users:id,name')
        ->first();

and my 'orders' model has method

public function parcels(){
        return $this->hasMany(OrderParcels::class);
    }
    public function users(){
        return $this->hasOne(User::class,'id','affixer_id');
    }

Note[edit]: I already know how to connect like this

$orderParcels = DB::table('order_parcels as op')
        ->leftjoin('orders as o','op.orders_id','o.id')
        ->leftjoin('users as u','o.affixer_id','u.id')
        ->leftjoin('situations as s','op.status','s.id')
        ->select('op.*','o.*','u.name','s.situations_name')
        ->where('op.orders_id',$id)->get();

but this is not working for me, for each parcels record it returns me orders and user info. I want once orders info and once user info.

CodePudding user response:

Laravel provides an elegant way to manage relations between models. In your situation, the first step is to create all relations described in your schema :

1. Model Order

class User extends Model {
    public function parcels()
    {
        return $this->hasMany(OrderParcels::class);
    }

    public function users()
    {
        return $this->hasOne(User::class,'id','affixer_id');
    }
}

2. Model Parcel

class Parcel extends Model {
    public function situations()
    {
        return $this->hasOne(Situation::class, ...);
    }
}

Then, you can retrieve all desired informations simply like this :

// Retrieve all users of an order 
$users = $order->users; // You get a Collection of User instances

// Retrieve all parcels of an order 
$parcels = $order->parcels; // You get a Collection of User instances

// Retrieve the situation for a parcel
$situations = $parcel->situations // You get Situation instance

How it works ?

When you add a relation on your model, you can retrieve the result of this relation by using the property with the same name of the method. Laravel will automatically provide you those properties ! (e.g: parcels() method in your Order Model will generate $order->parcels property.

To finish, in this situation where you have nested relations (as describe in your schema), you should use with() method of your model to eager load all the nested relation of order model like this :

$orders = Orders::with(['users', 'parcels', 'parcels.situations'])->find($id)

I encourage you to read those stubs of Laravel documentation :

Good luck !

CodePudding user response:

Use join to make a perfect relations between tables.

$output = Orders::join('users', 'users.id', '=', 'orders.user_id')
->join('order_parcels', 'order_parcels.id', '=', 'orders.parcel_id')
->join('situations', 'situation.id', '=', 'order_parcels.situation_id')
->select([
'orders.id AS order_id',
'users.id AS user_id',
'order.parcels.id AS parcel_id',
'and so on'
])
->where('some row', '=', 'some row or variable')->get();
  • Related