Laravel Eloquent Relations: An Advanced Guide (r) (r)

Jun 10, 2023
Two people hugging and learning about Laravel relationships

Share the news on

Often, there comes an occasion that any developer has to connect with databases. This is the point at that Eloquent becomes the Laravel object-relational modeler (ORM) allows the interaction procedure with tables from your database. It is simple and quick.

As an expert, you recognize and understand the 6 key types of relationships which will be discussed and reviewed.

What are the relationships that Eloquentians have with their language?

While working with tables in your relational database you identify relationships by the connection between tables. This allows you to manage and arrange your data efficiently which allows for better readability as well as the handling of information. There are three types of databases that are used in real-time:

  • one-to-1 - A single record within the table may be tied to a single, and only one table. For instance, a name or the Social Security number.
  • One-to-many can be associated with several records in another table. Similar to a writer, blogs and.
  • multiple-to-many entries - Multiple entries in tables are linked to a number of records in another table. Examples include students as well as the courses they are enrolled in.

Laravel provides a seamless way to manage and connect connections to databases using an object-oriented syntax inside Eloquent.

Along with those definitions Laravel also adds other relationships that include:

  • There are a variety of ways to go through
  • Polymorphic Relations
  • Many-to-many Polymorphic

Take, for example an online store that contains a variety of articles, each within its particular classification. Therefore, splitting the database into different tables makes sense from a practical point of view. This has its own set of issues of its own as you may not wish to go through each table.

It is possible to create a basic one-to-many relation using Laravel for us to assist during times the time you want to know more about product, and we are able to do this with the help of the Product model.

Database schema with three tables and a joint table representing a polymorphic relationship
A schema for a database that comprises three tables, as well as a joint table that represents the polymorphic relationship

One-To-One Relationship

As the primary relation Laravel provides, they connect two tables in a way so that one row of the table that is connected to only one row from the other table.

For more clarity on this, it's necessary to create two models with the individual movements:

php artisan make:model Tenant Php artisan make:model Rent

The present situation is involving two different models. The first is the tenant in addition to the other being their rent.

hasOne(Rent::class); 

It is due to the fact that it chooses to determine the foreign key relationship with the model's parent name (Tenant in this case) and Rent models assume that there is an tenant_id external key.

We can easily alter the method this manner, by adding an argument to use isOne method: method: isOne method:

return $this >hasOne(Rent::class, "custom_key");

Eloquent assumes there is a match between the specified foreign key and the main key of the parent (Tenant model). It will, by default seek to find that tenant's ID associated with the key id key within the record of Tenants. You can overwrite the tenant's ID by using a different argument inside isOne. isOne method. In this case it is in line with another key

return $this->hasOne(Rent::class, "custom_key", "other_key"); 

Once we've identified the one-to-1 relation between models and the models, we are able to utilize it in a simple manner, for example: this:

$rent = Tenant::find(10)->rent;

On this specific line, it will calculate the tenant's rent with the 10th digit if an ID exists.

One-To-Many Relationship

Similar to the relationship described above it will also define the connections to single parent models as well as models that have multiple children. The odds are that the tenant will be paying just one Rent payment because it's a regular installment, so it is likely to have multiple payments.

Our previous relationship was not perfect, which we have the ability to correct:

hasMany(Rent::class); 

Before we start the procedure for calculating rents a good idea to be aware of is that relationships can be query builders. So you can add further constraints (like rent that is due the interval between dates, minimum payment or minimum payments.) And then link them in order to get the desired result:

$rents = Tenant::find(10)->rent()->where('payment', '>', 500)->first();

As with the previous one it is possible to overwrite both foreign and local keys by arguing further:

return $this->hasMany(Rent::class, "foreign_key");
return $this->hasMany(Rent::class, "foreign_key", "local_key");

We now have all the information about the rent paid by tenants but, what can we do when we know the sum of the rent but would like to know who the tenant comes from? It is possible to use belongingsToproperty. isToproperty:

belongsTo(Tenant::class); 

We can now lease the house easily

$tenant = Rent::find(1)->tenant;

When using isTo as an isTo technique, we could further overwrite both keys to be both foreign and local keys, just as the way we previously did.

It's one of many relationships

As our Tenant model is designed to work with several Rent models, it's important to quickly access the most current or related model of the relationships.

The most efficient way to accomplish this is through combining hasOne ofMany and ofMany methods:

public function latestRent() return $this->hasOne(Rent::class)->latestOfMany(); public function oldestRent() return $this->hasOne(Rent::class)->oldestOfMany(); 

As a default, we're provided with data that is relevant to the key that is used as the primary. The data is then sorted. But, you are able to create your own filters with this method. ofMany method.

return $this->hasOne(Rent::class)->ofMany('price', 'min');

HasOneThrough and HasManyThrough Relations

The traversalmethods indicate that models we employ will need to be able to traverse through several models to make an alliance with the desired model. In this case, for instance, we could link the Rent to the Landlord. But, it is necessary for the rent to pass through the Tenant to get to the Landlord.

The tables' keys needed for this look like:

rent id - integer name - string value - double tenants id - integer name - string rent_id - integer landlord id - integer name - string tenant_id - integer

Once we've imagined what our tables will look like, we can make the following models:

hasOneThrough(Landlord::class, Tenant::class); 

The primary reason to use hasOneThrough hasOneThrough technique is to access the model you would like to have access to, while the second argument is the model you'll be navigating through.

Like in the past it's possible to change both the local and foreign keys. Since we now have two keys, there are two copies of each following order:

public function rentLandlord() return $this->hasOneThrough( Landlord::class, Tenant::class, "rent_id", // Foreign key on the tenant table "tenant_id", // Foreign key on the landlord table "id", // Local key on the tenant class "id" // Local key on the tenant table ); 

Likely, the "Has Numerous Through" relation in Laravel Eloquent is a useful feature when you're trying to gain access to data in a distant table through the intermediary table. Consider the following example using three tables:

  • the nation
  • users
  • Games

Each country has many players Every User takes part in numerous Games. It is our goal to locate all of the Games that are associated with a specific country by using the User table.

Tables are described in this way:

country id - integer name - string user id - integer country_id - integer name - string games id - integer user_id - integer title - string

Then you need to build the Eloquent model of each table that you own:

hasMany(User::class); public function games() return $this->hasManyThrough(Games::class, User::class); 
belongsTo(Country::class); public function posts() return $this->hasMany(Post::class); 
belongsTo(User::class); 

In the next step, we can call the game()method of the Country model in order to gain access to any game, since we've established that the "Has Many Through" relationship between Country and Game by using the User model.

games;

Many-to-Many Relationship

The connection between many and many is more complex. A good illustration is a person who plays many different roles. A role can also be assigned to many employees. This is what creates the multiple-to-many relation.

For this to be done in order to do this, we must include employee, roles, and rolestables.

Our table structure for databases should look something like:

employees id - integer name - string roles id - integer name - string role_employees user_id - integer role_id - integer

Based on the table structure of the relationship, it's easy to determine our Employee Model as part of the belongToMany Role model.

belongsToMany(Role::class); 

When we have defined the role, then we have access to all roles of employees and even filter these roles into:

$employee = Employee::find(1); $employee->roles->forEach(function($role) // ); // OR $employee = Employee::find(1)->roles()->orderBy('name')->where('name', 'admin')->get();

Similar to other techniques, we could replace both local as well as foreign keys with the belongsToMany method.

In order to define the inverted relationship of belongsToMany You can use the same procedure, but on the child method now and using parents as arguments.

belongsToMany(Employee::class); 

The purpose of The Intermediate Table

We may have spotted, when we use the many-tos-many relation, we are always supposed to use an intermediary table. In this instance we're using the employee_job_employees table.

The default pivot table we have includes only the ID attributes. If we want more attributes, we will be required to include them in the following manner:

return $this->belongsToMany(Employee::class)->withPivot("active", "created_at");

If we wish to shorten the time stamp pivot you can do this:

return $this->belongsToMany(Employee::class)->withTimestamps();

Another thing to be aware of is that we are able to change the name "pivot" to suit our needs. like to fit our preferences more effectively:

return $this->belongsToMany(Employee::class)->as('subscription')->withPivot("active", "created_by");
return $this->belongsToMany(Employee::class)->wherePivot('promoted', 1); return $this->belongsToMany(Employee::class)->wherePivotIn('level', [1, 2]); return $this->belongsToMany(Employee::class)->wherePivotNotIn('level', [2, 3]); return $this->belongsToMany(Employee::class)->wherePivotBetween('posted_at', ['2023-01-01 00:00:00', '2023-01-02 00:00:00']); return $this->belongsToMany(Employee::class)->wherePivotNull('expired_at'); return $this->belongsToMany(Employee::class)->wherePivotNotNull('posted_at');

Another amazing thing is the ability to order through pivots:

return $this->belongsToMany(Employee::class) ->where('promoted', true) ->orderByPivot('hired_at', 'desc');

Polymorphic Relations

The word Polymorphic is derived from Greek meaning "many kinds of." The application's design could include a variety of kinds, meaning that it could include more than one connection. Imagine that we're developing an application with blog posts, videos, and polls. People can post comments to each of them. So the design for comments can be found in blogs, Videos, in addition to Polls models.

One to One polymorphism

This type of relationship is similar to the normal one-toone relationship. It is the only difference being that the child model could be associated with multiple kinds of models with the same association.

For instance, consider an example of a Tenantand Landlord model. It could have a polymorphic relationship with WaterBill. WaterBill models.

Table structure could be as follows:

tenants id - integer name - string landlords id - integer name - string waterbills id - integer amount - double waterbillable_id waterbillable_type

The waterbillable_id column is used to represent identification of the tenant or landlordor tenantwhile the waterbillable_type contains the class name of the parent model. The type column can be used in a manner that's clear, to identify the parent model is returning.

A definition model of this type of relationship would be:

morphTo(); class Tenant extends Model public function waterBill() return $this->morphOne(WaterBill::class, 'billable'); class Landlord extends Model public function waterBill() return $this->morphOne(WaterBill::class, 'billable'); 

After we've got everything set up We can then get access to information from both the Tenant and the Landlord models.

waterBill; $landlord = Landlord::find(1)->waterBill;

The Polymorphic One to Many

Like the traditional one-to-many relationships. The main difference is that a child model can be part of multiple type of a model, using a single association.

In a social media platform such as Facebook it is possible to comment on videos, posts and polls in real time. By using a polymorphic model to multiple, we could make a single table that can be used for comments table to keep the comments for all the types of categories could be available. Our table structure will look something like this:

posts id - integer title - string body - text videos id - integer title - string url - string polls id - integer title - string comments id - integer body - text commentable_id - integer commentable_type - string

The commentable_id is the id of the record. the commentable_type being the class's type, and an eloquent individual knows what to search for. For the model structure it is very similar to polymorphic ones-to-many

morphTo(); class Poll extends Model public function comments() return $this->morphMany(Comment::class, 'commentable'); class Live extends Model public function comments() return $this->morphMany(Comments::class, 'commentable'); 

Now to retrieve the comments from the Live stream, you need to use the Find method by using the ID, and now we have access to the comment iterable class:

comments as $comment) // OR Live::find(1)->comments()->each(function($comment) // ); Live::find(1)->comments()->map(function($comment) // ); Live::find(1)->comments()->filter(function($comment) // ); // etc.

If we own the comments and would like to know who the author is, we can access the commentable method:

commentable; // type that allows commenting on Post, Video, or Poll Live

Polymorphic one of Many

For many apps that are huge that require a quick and efficient means of interacting to models, as well as among the models. There may be a need for a user's initial or final post that can be achieved using a mix of the morphOne and ofMany methods:

morphOne(Post::class, 'postable')->latestOfMany(); public function oldestPost() return $this->morphOne(Post::class, 'postable')->oldestOfMany(); 

The two approaches most recentOfMany as well as olderOfManyare getting the latest or the earliest model that relies on the model's initial key, which is the requirement that it was sortable.

There are times when we don't need to organize the posts by ID. maybe we altered the time of publication for certain articles, but we need them in the order that they were released, not according to their id.

This can be done by transferring two parameters to ofMany. ofMany method to help with this. The first element is the principal for us to select. The other parameter is the method of sorting:

morphOne(Post::class, "postable")->ofMany("published_at", "max"); 

In this way, you can create further more advanced connections to these! Consider this situation. We are asked to generate an inventory of current articles in the order they were published. This can be a challenge in the event that we have two articles with the same number for published_at and also when posts are scheduled to publish in the near future.

For this purpose, you can pass the order in which we would like to apply the filters to, using ofMany. ofMany method. In this way, we sort according to published_at, and if they're identical, the order will be based on ID. Furthermore, we could add the query function in this ofMany method to prevent all posts due to be published!

hasOne(Post::class)->ofMany([ 'published_at' => 'max', 'id' => 'max', ], function ($query) $query->where('published_at', '

Polymorphic Many to Many

The polymorphic many-to-many model is far more complicated than the regular one. A common scenario is that tags can be applied to many objects within your app. For instance, on TikTok there are tags that apply to video stories, shorts or other forms of content.

The polymorphic many-to-many enables us to make a table of tags for the shorts, videos, and stories.

The table structure is quite easy to understand:

videos id - integer description - string stories id - integer description - string taggables tag_id - integer taggable_id - integer taggable_type - string

Once the tables are ready, we can make the model and use the MorphToMany method. The method accepts names for the model class as well as the name of the relationship':

morphToMany(Tag::class, 'taggable'); 

And with this it is easy to establish the inverted relationship. For every model that contains children, we can use the term as"morphedByMany". morphedByMany process.

morphedByMany(Story::class, 'taggable'); public function videos() return $this->morphedByMany(Video::class, 'taggable'); 

If we are given a Tag that we would like to utilize, we are able to find all the videos and tales connected to the tag!

stories; $videos = $tag->stories;

Increase Eloquent to improve speed

Laravel is a flexible caching system that works with various backends, including Redis, Memcached, and file-based caching. Through caching the results of the queries, it is possible to reduce the volume of queries to databases and make your app more efficient and much more useful.

Furthermore, you may use Laravel's queries builder to build more complex queries that will further improve the speed of your app.

Summary

Eloquent relation are a powerful characteristic of Laravel that allows programmers to swiftly deal with information that is connected to one another. From one-to-one to many-to-many relationships Eloquent provides a simple and intuitive syntax to define and study the relationships.

This post was first seen on here