Mastering Laravel Eloquent ORM - The Eloquent Journey (PART 2)
Tags: php, laravel, database
Published: 2020-04-26 22:08:16

---
title: Mastering Laravel Eloquent ORM - The Eloquent Journey (PART 2)
published: true
description: understanding Eloquent Relationship
tags: #php, #laravel, #database
series: Mastering Laravel Eloquent ORM - The Eloquent Journey
cover_image: https://res.cloudinary.com/samfield/image/upload/v1578485140/Post%20Images/laravel-eloquent-orm-5a5d9744cab14.png
---

## Understanding Eloquent Relationships
Welcome once again. In this post I will be diving into Laravel Eloquent Relationships, if you missed the previous article, the link can be found at the bottom of this post.

As we all know that databases tables are often related to one another, let take for instance in a blogging platform, the users' table will be related to the posts, comments and replies tables, the comments table will be rated to the posts table, replies related to the comments table.  Eloquent comes packed with the underlying structure to enable us to manage the relations between our database tables, thereby making queries between our tables simple and flexible. 

Eloquent supports many types of relationships, which includes:
* One To One
* One To Many
* Many To Many
* Has One Through
* Has Many Through
* One To One (Polymorphic)
* One To Many (Polymorphic)
* Many To Many (Polymorphic)

Eloquent relationships are defined as methods in our model classes. The method names are decided by you, but make sure to give a name that can explain your relationship.

### One To One
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/i8b2rxzw7pbdavwb8w7y.png)

The One to One relationship is a type of relationship whereby a model is related to another model by a single data. let's say we have Profile Model that will hold the profile information about a user in our database. We will expect our users to have only one profile and a profile should belong to a single user. This kind of relationship is a `one to one relationship`, and to achieve this relationship, we will expect our profiles table to have a connection to our users' table using the `foreign key` constraint by adding a column to create this connection.

`Sample Profile table`
<table>
<thead>
<tr>
<th>id</th>
<th align="center">user_id</th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td align="center">1</td>
<td>20 Markson St.</td>
</tr>
</tbody>
</table>

```php
  $table->unsignedInteger('user_id')
  
  $table->foriegnKey('user_id')->references('id')->on('users')->onDelete('cascade')

```
adding the above to our profile table migration, laravel now uses this to create our relationship between our models.

we can now define our relationship between our models. since the foreign key is on the Profile model, we can now use the eloquent `hasOne()` method to let eloquent bind our User model to the profile model that a user in our users' table has a profile by
```php
  /**
  *Returns an Eloquent relationship
  **/
  public function profile()
  {
    return $this->hasOne(Profile::class);
  }
```
Here eloquent expect that we have a `user_id` column existing in the profile table, but in suituation you have a different column name for our foriegn key representing our users table,
<table>
<thead>
<tr>
<th>id</th>
<th align="center"><code>custom_user_id</code></th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td align="center">1</td>
<td>20 Markson St.</td>
</tr>
</tbody>
</table>

we can tell Eloquent by providing the second parameter to our `hasOne()` method
```php
  return $this->hasOne(Profile::class, 'custom_user_id');
```
Eloquent also expect that on our user table the primary key is `id`, but in cases we have a different primary key other that `id`, 

`Sample User Table`
<table>
<thead>
<tr>
<th align="center"><code>user_id</code></th>
<th>name</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center">1</td>
<td>Samfield Hawb</td>
</tr>
</tbody>
</table>


we can pass the third parameter
```php
  return $this->hasOne(Profile::class, 'custom_user_id','user_id');
```
with this we have a relationship between the User model and Profile model. Now let create a reverse of the relationship using the Eloquent `belongsTo()` method. we will define the reverse now in our Profile Model class;
```php
/**
*Returns an Eloquent Relationship
*/
public function user()
{
  return $this->belongsTo(User::class);
}
```
Also here eloquent will try to match `user_id` on the profiles table with an id on the users' table, and in situation you have a different column name for our foreign key on our profile table,
<table>
<thead>
<tr>
<th>id</th>
<th align="center"><code>custom_user_id</code></th>
<th>address</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td align="center">1</td>
<td>20 Markson St.</td>
</tr>
</tbody>
</table>
we can tell Eloquent by providing the second parameter to our `belongsTo()` method
```php
  return $this->belongsTo(User::class, 'custom_user_id');
```
Eloquent also expect that on our user table the primary key is `id`, but in cases we have a different primary key other than `id`,
<table>
<thead>
<tr>
<th><code>user_id</code></th>
<th>name</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Samfield Hawb</td>
</tr>
</tbody>
</table>
we can pass a third parameter
```php
  return $this->belongsTo(User::class, 'custom_user_id','user_id');
```
With this set up, we can now use this relationship to perform a query between this two models 
```php
  $user = \App\User::find(1);
  $user->profile;//the profile can now be gotten by
  
  //likewise in the opposite direction
  $profile = \App\Profile::find(1);
  $profile->user; //gets the user that owns the profile
  $profile->user->name; //returns the name of the user
```
### One To Many
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/4bvvmknn3xkh7fpl4er5.png)

This is a relationship whereby a model is related to another model by many records, for instance, A user in a blogging application can have many blog posts, comments, as well as replies, likewise a comment, post, or replies can belong to a user in the users' table. Eloquent provides us with `hasMany()` method to create this kind of relationship between our models. So let's define this kind of relationship between a User model and a Post Model, in a User model we add;

`Sample Posts Table`
<table>
<thead>
<tr>
<th>id</th>
<th>title</th>
<th>content</th>
<th align="center"><code>user_id</code></th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mastering laravel Eloquent ORM</td>
<td>content</td>
<td align="center">1</td>
</tr>
</tbody>
</table>


```php
public function posts()
{
  return $this->hasMany(Post::class);
}
```
here Eloquent expect a foriegn key column `user_id` in our posts table, but i situation we have a different name,
<table>
<thead>
<tr>
<th>id</th>
<th>title</th>
<th>content</th>
<th align="center"><code>custom_user_id</code></th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mastering laravel Eloquent ORM</td>
<td>content</td>
<td align="center">1</td>
</tr>
</tbody>
</table>
a second parameter can be pass to the `hasMany()` method,
```php
return $this->hasMany(Post::class,'custom_user_id');
```
likewise if we have a diffent primary key for the parent model `User` from the `id` column which Eloquent expect, we can also pass in a third parameter to the `hasMany()` method
```php
return $this->hasMany(Post::class,'custom_user_id','user_id')
```
we have created a relationship for our User model to the Post model. Now let create the reverse of the relationship, Post model to the User model, this can be achieve also with the Eloquent `belongsTo()` method ;
```php
public function user()
{
  return $this->belongsTo(User::class);
}
```
here eloquent will still try to match `user_id` on the posts table with an id on the users' table, in situation you have a different column name for our foreign key on our posts table, we can tell Eloquent by providing the second parameter to our `belongsTo()` method
```php
  return $this->belongsTo(User::class, 'custom_user_id');
```
Eloquent still expect that on our user table the primary key is `id`, but in cases we had a define primary key name other that `id`, we can pass a third paramater to the `belongsTo()` method;
```php
  return $this->belongsTo(User::class, 'custom_user_id','user_id');
```
with this set up now, we can now make use of eloquent to query data between the models. Lets get all the posts made by a user with `id` of 1 from the database;
```php
  $user = \App\User::findOrFail(1); //we retrieve the user
  
  //lets print out the title for all the post made 
  foreach ($user->posts as $post)
  {
    echo $post->title;
  }
  
```
we have seen how easy eloquent has made retrieving the post here, with this relationship, we can create a post that binds to a particular user;
```php
  $user = \App\User::find(1);
  $user->posts()->create([
    //we supply all keys representing the column name and the value in
    // 'key' => 'value'
  ]);
```
with the above code snippet, Eloquent automatically extracts the `user_id` from the $user object to create a blog post. likewise, using the `createMany()` method on the relationship can allow you to store many blog posts at a time to a user. We will come to this later.
Let's say we want to get the name of a user that owns a post,  we can easily achieve this too from the relationship;
```php
  $post = \App\Post::find(1);
  echo $post->user->name;
```
## Many To Many
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/2m6cjcjjwg2r42u0zo82.png)

At times when building a web application, we want to related values in a table with other values in another, for instance, if we want to introduce a role system into our blog, a user can have multiple roles, also a role can belong to multiple users. Laravel Eloquent provides us with the many to many relationships, to achieve this, we will need to create another table using the laravel migration that will store up this relationship, `create_role_user_table`,
```shell
$ php artisan make:migration create_role_user_table --table=role_user
```
in the up method of our generated migration file, we can add
```php
  $table->unsignedInteger('user_id');
  $table->unsignedInteger('role_id');
  //foriegn key
  $table->foriegnKey('user_id')->references('id')->on('users')->onDelete('cascade');
  $table->foriegnKey('role_id')->references('id')->on('roles')->onDelete('cascade')
```
here, eloquent uses these two columns to fetch our data when needed.

`Sample role_user table with data`
<table>
<thead>
<tr>
<th>user_id</th>
<th>role_id</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>3</td>
</tr>
<tr>
<td>2</td>
<td>4</td>
</tr>
</tbody>
</table>
We can see how this user with `id 1` has 3 roles with `ids 1, 4, 3`.
Now on our User model we can now define our relationship using the `belongsToMany()` method provided for use by Eloquent Model class
```php
public function roles()
{
  return $this->belongsToMany(Role::class);
}
```
Eloquent seeing this relationship will try to determine the table for we created above by joining the two related models in alphabetical other separated by an underscore  `role_user`. In situations we declared a name  other than this, we can pass a second parameter to our `belongsToMany` method to tell Eloquent where to find the relationship.
```php
   return $this->belongsToMany(Role::class,'custom_role_user');
```
Also, if we had custom keys for the table other than the expected value, we can pass the third parameter as a foreign key for the model we are defining the relationship and a fourth parameter for the foreign key to the relating model
```php
    return $this->belongsToMany(Role::class,'custom_role_user','custom_user_id','custom_role_id');
```
we can then define the inverse of the relationship on our role model too, which will enable use query all users that is tied to a particular role.
```php
public function users()
{
  return $this->belongsToMany(User::class);
}
```
With the relationships define, we can then fetch our data from the database using eloquent ORM;
```php
$user = \App\User::find(1);
foreach ($user->roles as $role)
{
  echo $role->name
}

$role = \App\Role::find(1);
foreach($role->users as $user)
{
  echo $user->name;
}
```
we can assign a role to a user using the relationship and the `attach()` method from the Model class
```php
$user = \App\User::find(1);
$user->roles()->attach(1); //assigned role with id 1 to the user

$user->roles()->attach([2,3,4]); //assigned roles with ids 2,3,4 to the user
```
also roles can be remove from users using the eloquent `detach()` method;
```php
$user = \App\User::find(1);
$user->roles()->detach(1); //remove role with id 1 to the user

$user->roles()->detach([2,3,4]); //remove roles with ids 2,3,4 to the user
```
## Conclusion
So far we have covered the `One to One`, `One To Many`, and `Many To Many` relationship types made available by eloquent, in the next article we will look into the remaining types. Thank you for following this far.

Links to Previous articles:
- [Mastering Laravel Eloquent ORM - The Eloquent Journey (PART 1)](https://dev.to/teamxenox/mastering-laravel-eloquent-orm-the-eloquent-journey-part-1-1571)