laravel

Laravel eloquent polymorphic relationships explained


Eloquent ORM is one of the most exciting and powerful built-in features in Laravel. Before we start we’ve to understand, what ORM means. ORM means object relational mapper. It handles database operations by representing data as objects. Database records or we better know them as tables are often related to each other. Eloquent maintains these relationships very easily through a series of common relationships. Laravel’s eloquent Polymorphic relationship allows a model to belong to more than one other model on a single association.

Prerequisite :

To complete this tutorial all you need to have is a configured computer, a text editor, a web browser, a web server installed on your computers like Xampp or WampServer, composer(package manager), and a basic understanding of PHP and laravel.

In this tutorial, we will use Sublime Text 3 as a text editor, xampp server, and Google Chrome as a web browser.

Steps To Be Followed:

In this tutorial, you’re going to learn about polymorphic relationships step by step with examples. The following steps are-

  • Download Laravel 8 application
  • Setup Database
  • Create Routes
  • Create Controller
  • Create Blade View
  • Run Development Server
  • Eloquent relationships (Polymorphic)
    • One To One
    • One To Many
    • Many To Many
  • Conclusion

Download Laravel 8 application

Before we start, we need to download and set up a laravel application. With composer installed on your computer, you can download a laravel project with the following command-

composer create-project laravel/laravel laravel-eloquent-relations

Setup Database

To work with Eloquent ORM, obviously, we’re going to need a database. Right? Now the project is installed, we need to set up the database. You can find out the .env file on your laravel project and set up the database name. Like this-

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel-eloquent
DB_USERNAME=your_database_username
DB_PASSWORD=your_database_password

You can name your project and database name as you want.

Create Routes

Now we need to make a route. In laravel routes makes a relationship with your laravel controller. In our installed laravel project there is a file called web.php. Routes are written in that file. We need to create a route to view the database results. In this tutorial, we’re going to use the same route for all the examples. Because our main concern is to learn all the eloquent relationships. You can create a route like this-

Route::get('/index',[App\Http\Controllers\UserController::class,'view'])
->name('user-index');

Create Controller

After creating the route, now we need a controller. The controller is a class where we handle requests, implement logic. In your laravel project, they are stored in the app/Http/Controllers directory. In this tutorial, we’re going to use the same controller for all the examples. You can practice with different controllers if you want. You can use the php artisan command to create a controller-

php artisan make:controller UserController

We’re going to use the name UserController. Inside the controller, we’ll need a function called view to display the data.

class UserController extends Controller
{
    public function view(){
        return view('User.view');
    }
}

Here, the view() function returns a blade file that is stored under the User folder.

Run Development Server:

We’re going to run the development server after every relationship example. To run the development server, the PHP artisan command is-

php artisan serve

Eloquent relationships(Polymorphic):

One To One:

A one-to-one polymorphic relation is similar to a typical one-to-one relation. Suppose, in a system there are two types of users called Student and Teacher. A student can have a profile as well as a teacher. So, normally we need two tables for students and teachers. Laravel polymorphic relations allow us to work with a single table to store both student and teacher profiles.

Here, we created an All_profile table and passes two extra fields called allprofileable_type and allprofileable_id. These two fields store the profiles with type and id, which means when a student stores profile it stores the all_profileable type as a student, and when a teacher stores profile it stores the all_profileable type as a teacher.

language-php

Now, let’s examine the model definitions needed to build this relationship. Like this-

//All_profile model
public function allprofileable(){
   return $this->morphTo();
}

this morphTo() defines that, this model may be associated with other models with polymorphic relationships. It’ll become clear in coming examples. Now we also have to define polymorphic into those models, that we’re trying to connect with the All_profile.

Student.php:

public function allprofile(){
   //Method(allprofileable) from AllProfile model
   return $this->morphOne(AllProfile::class, 'allprofileable'); 
}

Teacher.php:

public function allprofile(){
   //Method(allprofileable) from AllProfile model
   return $this->morphOne(AllProfile::class, 'allprofileable'); 
}

In those allprofile() methods, we’ve to provide the Allprofile class and as a second parameter the name we’ve used in the database table field which is allprofileable. You’ve to use the same name as the database field name. Now, let’s look into the controller-

For student:

public function view(){
    $studentData= Student::find(1);
    return view('User.view',compact('studentData'));
}

For teacher:

public function view(){
    $teacherData= Teacher::find(1);
    return view('User.view',compact('teacherData'));
}

In this UserController, we simply call the Student and Teacher models, and with the find(1) method we can get all the data of the user whose id is 1. Then we pass the retrieved data through a compact function. Now, let’s get to the view file-

For student:

//View.blade.php
<h1>(morphOne) polymorphic relationship</h1>
<div class="container">
    <h3>Profile</h3><hr>
    <p>Name:<b> {{$studentData->allprofile->full_name}} </b></p>
    <p>Email:<b> {{$studentData->allprofile->email}} </b></p>
</div>

For teacher:

//View.blade.php
<h1>(morphOne) polymorphic relationship</h1>
<div class="container">
    <h3>Profile</h3><hr>
    <p>Name:<b> {{$teacherData->allprofile->full_name}} </b></p>
    <p>Email:<b> {{$teacherData->allprofile->email}} </b></p>
</div>

In this view.blade.php file, we get the profiles through the allprofile() functions implemented in Student.php and Teacher.php.

All_profiles table:

OUTPUT(Student):

Laravel eloquent polymorphic relationships

OUTPUT(Teacher):

Laravel eloquent polymorphic relationships

One To Many:

Now consider, on this system, a student can comment as well as a teacher. The database demo diagram is given below-

Laravel eloquent polymorphic relationships

So, again the concept remains the same. We’re going to create an All_comments table that can store multiple comments data from both of the users.

Now, let’s examine the model definitions needed to build this relationship-

//Morph many
public function commentable(){
    return $this->morphTo();
}

Now we also have to define polymorphic into those models, that we’re trying to connect with All_comment() model-

Student.php:

//Morph many
public function comments(){
    //Method(commentable) from AllComment model
    return $this->morphMany(AllComment::class, 'commentable'); 
}

Teacher.php:

//Morph many
public function comments(){
    //Method(commentable) from AllComment model
    return $this->morphMany(AllComment::class, 'commentable'); 
}

Now we’re using morphMany() method, because of one to many relationship. In those comments() methods, we’ve to provide the AllComment class and as a second parameter the name we’ve used in the database table field which is commentable. You’ve to use the same name as the database field name. Now, let’s look into the controller-

For student:

public function view(){
    $studentData= Student::find(1)->first();
    return view('User.view',compact('studentData'));
}

For teacher:

public function view(){
    $teacherData= Teacher::find(1)->first();
    return view('User.view',compact('teacherData'));
}

In this UserController, we simply call the Student and Teacher models, and with the find(1) method we can get all the data of the user whose id is 1 and pass the retrieved data through a compact function. Any relationship that has Many in its name, for example, morphMany() will always return a collection object. So. we need to use the first() function to get the data. Now, let’s get to the view file-

For student:

//View.blade.php
<h1>(morphMany) polymorphic relationship</h1>
<div class="container">
  @foreach($studentData->comments as $data)
    <p>Name:<b> {{ $data->full_name }} </b></p>
    <p>Comment:<b> {{ $data->comment }} </b></p>
  @endforeach
</div

For teacher:

//View.blade.php
<h1>(morphMany) polymorphic relationship</h1>
<div class="container">
  @foreach($teacherData->comments as $data)
    <p>Name:<b> {{ $data->full_name }} </b></p>
    <p>Comment:<b> {{ $data->comment }} </b></p>
  @endforeach
</div>

In this view.blade.php file, we looped through the retrieved data from the Student and Teacher models using @foreach and by using the morphMany() method which is implemented into those models, we can access the All_comments table.

All_comments table:

Laravel eloquent polymorphic relationships

OUTPUT(Student):

Laravel eloquent polymorphic relationships

OUTPUT(Teacher):

Many To Many:

Let’s think of a scenario, where a student can take multiple subjects and a teacher also can have multiple enrolled subjects and a subject table where we’re storing all the subject information. Rather than creating multiple tables for students and teachers, we can combine them into a table using the polymorphic many to many relationship. The diagram is given below-

Laravel eloquent polymorphic relationships

We can make a pivot table called Courseable where we can store the user type, id, and also the subject id.

Now we have to define polymorphic relationships into the Student, Teacher, and the Subject model.

Student.php:

public function subjects()
{
    return $this->morphToMany(Subject::class, 'courseable');
}

Teacher.php:

public function subjects()
{
    return $this->morphToMany(Subject::class, 'courseable');
}

We’ve to define the morphToMany() function into the Student and Teacher models and as a second parameter the table field name ‘courseable’ of the courseable table.

Subject.php:

//Morphed by many
public function students(){
    return $this->morphedByMany(Student::class, 'courseable'); 
}

//Morphed by many
public function teachers(){
    return $this->morphedByMany(Teacher::class, 'courseable'); 
}

In the Subject model, morphedByMany() means this model is connected with many students and teachers. Now, let’s look into the controller-

For student:

public function view(){
    $studentData= Student::find(1);
    return view('User.view',compact('studentData'));
}

For teacher:

public function view(){
    $teacherData= Teacher::find(1);
    return view('User.view',compact('teacherData'));
}

Now, the logic is the same as before, so let’s move into the view file-

For student:

//View.blade.php
<h1>(morphToMany) polymorphic relationship</h1>
<div class="container">
  <h3>Student name: <b>{{$studentData->full_name}}</b></h3><hr>
  <h4>Enrolled subjects:</h4>
  @foreach($studentData->subjects as $subject)
    <p><b> {{ $subject->subject_name }} </b></p>
  @endforeach
</div>

For teacher:

//View.blade.php
<h1>(morphToMany) polymorphic relationship</h1>
<div class="container">
  <h3>Student name: <b>{{$teacherData->full_name}}</b></h3><hr>
  <h4>Enrolled subjects:</h4>
  @foreach($teacherData->subjects as $subject)
    <p><b> {{ $subject->subject_name }} </b></p>
  @endforeach
</div>

In this view.blade.php file, we access the courseable table from where we can access all the subject data that was taken by our students and teachers. We can use the subjects() method that was implemented into Student and Teacher models.

Courseable table:

OUTPUT(Student):

Laravel eloquent polymorphic relationships

OUTPUT(Teacher):

Laravel eloquent polymorphic relationships

Conclusion:

In this tutorial, we discussed Laravel’s eloquent polymorphic relationships. We can use the query builder also to handle the database process. But the eloquent ensures a higher quality between application logic and presentation. It reduces the number of queries, database tables, and load time which makes the application faster. It’s easy to use, but to understand it better you’ve to understand the concept of Laravel MVC architecture and the eloquent relationships. So, practice the above examples with your own. Good luck.


Share on social media

//