# Advanced use of linked tables

  • 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.

Database Model

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 Ordes ITF User 1

Let's look at the relations between the models that we have defined so far:

IMPORTANT

Always use the name of the relationship in the with() method, not the name of the table!

# Example setup

  • We want to define 3 queries
    1. 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)
    2. 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)
    3. 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

IMPORTANT

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.

  • Open the pages in the browser
  • At this point we only see the starting tables

# Retrieve all the information from the chain

  • Line 5 & 12: to get all the information from a chain of linked tables you only have to concatenate the name of the relations with a dot
  • Line 19: to get all the information from relations on the left side and on the right side, the names of the relations are separated by a comma




 
 





 
 





 
 




class DemoController extends Controller
{
    public function orderlines()
    {
        $orderlines = Orderline::with('order.user')
            ->get();
        return compact('orderlines');
    }

    public function users()
    {
        $users = User::with('orders.orderlines')
            ->get();
        return compact('users');
    }

    public function orders()
    {
        $orders = Order::with('orderlines', 'user')
            ->get();
        return compact('orders');
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# Skip one level down

  • 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:

Skip more than one level?

  • To exclude (filter) some fields from the linked tables, you have to split the relations in multiple parts
  • Let's start with selecting all the information about the first orderline
  • First, replace the single notation inside with('order.user') with with('order', 'order.user') or with with(['order', 'order.user'])
  • When you reload the pages, nothing has changed yet, but now we can apply some filters on each table separately
  • And of course, you can also hide some properties (real properties and calculated properties) from the master table

# Add additional query conditions

  • Until now, we can get linked tables and filter some of their fields, but what if we want some additional conditions on the nested tables?
  • We can:
    • add a scope to the model (like we did with the filter by artist or record name on the shop page)
    • use a closure function in the with() method
  • Suppose we want to sort the orderlines (the records a user ordered) by artist and not by id (the default order) with a closure function
  • Now, let's add a closure function to sort the orderlines by artist
Last Updated: 4/21/2023, 4:59:05 PM