In this section, we show some advanced use cases on how to get data from a chain of linked tables
In our site we only have three tables (orderlines, orders and users) linked to each other.
However, the logic we describe here will be the same if you have more linked tables (four, five, ten, ...),
as long as you correctly define the relations (belongsTo() and hasMany()) inside the Eloquent models.
To demonstrate this, we reset the database and Jane Doe (user with id 2) places a 2 new orders
First order has three orderlines:
1 x Fleetwood Mac - Rumours
1 x David Bowie - The Rise and Fall of Ziggy Stardust and the Spiders from Mars
1 x Roxy Music - Siren
Second order has two orderlines:
1 x Front 242 - Front by Front
1 x Ministry - Land of Rape and Hony
Let's look at the relations between the models that we have defined so far:
User model: method orders() (one-to-many relation)
classUserextendsAuthenticatable{publicfunctionorders(){return$this->hasMany(Order::class);// a use has many orders}}
1 2 3 4 5 6 7
Order model:
method user() (many-to-one relation)
method orderlines() (one-to-many relation)
classOrderextendsAuthenticatable{publicfunctionuser(){return$this->belongsTo(User::class)->withDefault();// an order belongs to a user}publicfunctionorderlines(){return$this->hasMany(Orderline::class);// an order has many orderlines}}
The first query starts from the most right table (orderlines) and should retrieve all the information from the orders table (the order to which this orderline belongs) and from the users table (the user to which this order belongs)
The second query starts from the most left table (users) and should retrieve all the information from the orders table (the orders placed by this user) and from the orderlines table (the orderlines of these orders)
The last query starts from the middle table (orders) and should retrieve all the information from the orderlines table (the orderlines of this order) and from the users table (the user to which this order belongs)
First create some extra routes in routes/web.php and a new (Laravel) controller with the command: php artisan make:controller Admin/DemoController
Route::middleware(['auth','active','admin'])->prefix('admin')->name('admin.')->group(function(){
Route::redirect('/','/admin/records');...
Route::get('orders', Orders::class)->name('orders');// yes, you can nest prefixes and groups if you want :-)
Route::prefix('demo')->name('demo.')->group(function(){
Route::get('orderlines',[DemoController::class,'orderlines'])->name('orderlines');
Route::get('users',[DemoController::class,'users'])->name('users');
Route::get('orders',[DemoController::class,'orders'])->name('orders');});});
We use a controller to explain the use of linked tables and relationships. Of course, you can also use
this method to provide your Livewire components with data. So for your project, you apply this method
in Livewire components.
It's possible to skip one level down (not up) in the chain of relations
In our data model, the only place we can demonstrate this is with the User model and the Order model:
E.g: we want to retrieve the orderlines from a user without fetching the orders they belong to
To achieve this, we have to use the with() method, but we have to define the relation in the model with hasManyThrough()
Add the distance relation to the User model:
Add the method orderlines() with a hasManyThrough() relation
classUserextendsAuthenticatable{publicfunctionorders(){return$this->hasMany(Order::class);// a use has many orders}publicfunctionorderlines(){return$this->hasManyThrough(Orderline::class, Order::class);// a user has many orderlines through the orders}}
1 2 3 4 5 6 7 8 9 10 11 12
Replace with('orders.orderlines') with with('orderlines')