In Laravel, Eloquent relationships are like bridges between your database tables, built using object-oriented principles. They can handle related records easily with complex SQL queries.

Here’s the beauty of it: with Eloquent relationships, you can fetch, edit, and query related data using clean, intuitive methods. It’s a way to make your database interactions feel almost effortless.

To simplify how you work with connected tables. Instead of worrying about complicated SQL joins, you can define relationships like hasOne, belongsTo, hasMany, or belongsToMany right in your models. These tools let you mirror real-world connections—like users and profiles, posts and comments, or roles and permissions—with ease.

But that’s not all. Eloquent relationships come packed with advanced features like eager loading (to avoid query bloat), dynamic constraints, and even polymorphism (so you can handle different types of related models seamlessly). These features don’t just make your code cleaner—they make it faster, easier to maintain, and more scalable.

Features of Eloquent Relationships:

Object-Oriented: Interact with relationships like objects rather than raw SQL.

Readable Syntax: Use expressive methods like hasOne, belongsTo, hasMany, etc.

Simplified Queries: Eloquent automatically generates and optimizes SQL queries for relationships.

Dynamic Behavior: Fetch, create, update, or delete related models easily.

Benefits of Eloquent Relationships:

Efficiency: Query related models using optimized SQL.

Readability: Expressive, clean, and intuitive code.

Maintainability: Centralized definition of relationships simplifies future updates.

Flexibility: Handle complex relationships like polymorphism with ease.

There are different types of database relationships and we will practice them:

1. One-To-One Relationship

Being the first basic relation Laravel offers, they associate a single relationship between two models. For example: A User has one Profile.

By using the below code, we can create two models with their own migration: 


php artisan make:model User

Php artisan make:model Profile

At this point, we have two models, one being the User and the other being their Profile.

User Model

&lt?php

namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
    * Get the profile of a user
    */
    public function profile() 
    {
        return $this->hasOne(Profile::class);
    }
}

Profile Model

&lt?php

namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Profile extends Model
{
    public function user() 
    {
        return $this->belongsTo(User::class);
    }
}

Eloquent establishes the foreign key relationship by referencing the parent model’s name (in this case, User). As a result, the Profile model is designed to incorporate a user_id foreign key.

We can easily overwrite it with an additional argument using the hasOne method:

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

Eloquent also requires that the defined foreign key matches the primary key of the parent (User model). It will automatically search for a match between tenant_id and the id key of the User record. By including a third argument in the hasOne method, we have the ability to override and make it correspond to a different key.

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

2. One-To-Many Relationship

We can define a One-to-Many relationship between a single parent model and multiple children model. It is like one post has many comments. Here we can fix the mistakes we had in our previous relationship.

&lt?php

namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    /**
    * Get the comments of a Post
    */
    public function comments() 
    {
        return $this->hasMany(Comment::class);
    }
}

In this case, we have all the comments of a post, but we need to figure out which comment belongs to which post. Here, we can use the belongs to property:

&lt?php

namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    /**
    * Return the post for the comment
    */
    public function post() 
    {
        return $this->belongsTo(Post::class);
    }
}

3. Many-To-Many Relationship

The many-to-many relationship is a bit complicated. We can use an example as an user that has multiple roles. A role is also assigned to multiple users. This is the theory of many-to-many relationship.To start this, we must need the users, roles and users_role tables. We can design our database like this:

users
id - integer
name - string

roles
id - integer
name - string

users_role
user_id - integer
role_id - integer

As, we have the data table structure, now we can define our Employee model to belongsToMany model:

&lt?php

namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function roles() 
    {
        return $this- >belongsToMany(Role::class);
    }
}

We can define the inverse relationship of the belongsToMany method. We can use the child method with the parent as an argument:

&lt?php

namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    public function users() 
    {
        return $this->belongsToMany(User::class);
    }
}

4. Has-One-Of-Many Relationship:

In Laravel, the hasOne relationship is specialized into the Has-One-Of-Many relationship. It enables you to extract a single record from a linked table according to a condition, such as the record that has the highest or lowest value in a column, is the oldest or most recent, or other restrictions.

When you need to obtain only one of a parent model’s numerous associated records depending on a certain rule, this connection is especially helpful.

Use Cases for Has-One-Of-Many

  • A User has many Orders, but you want to find only the latest order.
  • A Product has many Prices, but you need the highest price.
  • A Customer has many Subscriptions, but you want the most recent active subscription.

We can do this easily by using the hasOne relationship with additional limitations using the ->ofMany() method.

For latestOrder relationship:

class User extends Model
{
    public function latestOrder()
    {
        return $this->hasOne(Order::class)->latestOfMany();
    }
}

For the oldest order:

class User extends Model
{
    public function oldestOrder()
    {
        return $this->hasOne(Order::class)->oldestOfMany();
    }
}

5. HasOneThrough and HasManyThrough Relationships

With HasOneThrough and HasManyThrough relationships in Laravel, we can relate models through an association model. These relationships are helpful where the parent model has no direct relationship with the target model but through another model.

HasOneThrough Relationship: We can compare a Country has one CapitalCity, but the CapitalCity is defined through the State model.

Database Structure: 

Countries Table:
id (Primary Key)
name

States Table:
id (Primary Key)
country_id (Foreign Key)

CapitalCities Table:
id (Primary Key)
state_id (Foreign Key)
name

Model Definitions

class Country extends Model
{
    public function capitalCity()
    {
        return $this->hasOneThrough(CapitalCity::class, State::class);
    }
}

HasManyThrough Relationship

A HasManyThrough relation connects a single record from one table to numerous records from another table via a bridge table. We can compare a Country with many Posts, but the Posts are linked through the User model.

Database Structure

Countries Table:
id (Primary Key)
name

Users Table:
id (Primary Key)
country_id (Foreign Key)

Posts Table:
id (Primary Key)
user_id (Foreign Key)
title

Model Definitions

class Country extends Model
{
    public function posts()
    {
        return $this->hasManyThrough(Post::class, User::class);
    }
}

6. Polymorphic One-to-One Relationship

A polymorphic one-to-one relationship in Laravel refers to a relationship type where a model can associate itself with several other models, based on only a single association. This is especially beneficial when there is a need to create a relationship between models that are of the same type. For instance, one model needs to have an image or an address only once without creating any other tables or form.

We can compare a User and a Post both can have a single Image. or a Product and an Order both can have a single Note.

Database Structure

users
   id – integer
    name – string

posts
   id – integer
    name – string

images
   id – integer
   imageable_id
    imageable_type

Model Definitions

Image Model: The Image model defines the polymorphic relationship:

class Image extends Model
{
    public function imageable()
    {
        return $this->morphTo();
    }
}

User Model: The User model can have a single polymorphic image:

class User extends Model
{
    public function image()
    {
        return $this->morphOne(Image::class, 'imageable');
    }
}

Post Model: The Post model can also have a single polymorphic image:

class Post extends Model
{
    public function image()
    {
        return $this->morphOne(Image::class, 'imageable');
    }
}

Getting the Image of a User

$user = User::find(1);
$image = $user->image;

echo $image->path;

Getting the Image of a Post

$post = Post::find(1);
$image = $post->image;

echo $image->path;

7. Polymorphic One To Many

A Polymorphic One-to-Many relationship means a model can belong to other models more than one, and instead of linking a single child, it may link more than one child. This feature is particularly useful when a number of models have the same type of relationship, like comments or tags, without establishing a new table or relationships for each model.

We can compare a Post and a Video can have multiple Comments or a Photo and a Product can have multiple Tags.

Database Structure

posts 
   id – integer
   title – string
    body – text

videos
   id – integer
   title – string
    url – string

Model Definitions

Comment Model

class Comment extends Model
{
    public function commentable()
    {
        return $this->morphTo();
    }
}

Post Model

class Post extends Model
{
    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

Video Model

class Video extends Model
{
    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

Get All Comments for a Post

$post = Post::find(1);
foreach ($post->comments as $comment) {
    echo $comment->content;
}

Get All Comments for a Video

$video = Video::find(1);
foreach ($video->comments as $comment) {
    echo $comment->content;
}

8. Polymorphic One of Many

A Polymorphic One-of-Many Relationship enables you to get a single child record (out of many such ones) in a complex one-to-many relationship by using desired specifications like last, first, or maximum value. This feature helps to fetch the most appropriate piece of data and reduce the number of queries as well. Besides, it becomes possible to process complex relations within your application easily through Laravel’s powerful relationship methods.

We can compare a Post and a Video can have multiple Comments, but you only want the latest comment or a Product and a Photo can have multiple Tags, but you want the most popular tag.

Models

Comment Model

class Comment extends Model
{
    public function commentable()
    {
        return $this->morphTo();
    }
}

Post Model

class Post extends Model
{
    public function latestComment()
    {
        return $this->morphOne(Comment::class, 'commentable')->latestOfMany();
    }
}

Video Model

class Video extends Model
{
    public function oldestComment()
    {
        return $this->morphOne(Comment::class, 'commentable')->oldestOfMany();
    }
}

Get latest Comment for a Post

$post = Post::find(1);
$latestComment = $post->latestComment;

echo $latestComment?->content ?? 'No comments found.';

Get oldest Comment for a Video

$video = Video::find(1);
$oldestComment = $video->oldestComment;

echo $oldestComment?->content ?? 'No comments found.';

8. Polymorphic Many to Many

The Polymorphic Many-to-Many Relationship is one of the strongest things in Laravel as it enables the multiple models to have a common dependency with a shared resource like tags, categories, or likes. You can control these associations by making use of only one pivot table, which is not only the quickest and most efficient, but also contributes to the absolutely clean database schema. With Laravel’s easy syntax to show things like these, you can define, retrieve, and deal with these data sets in your application.

We can compare a Post and a Video can both have many Tags, a User can like multiple models, such as Posts and Comments or a Photo and a Product can belong to multiple Categories.

Models

Tag Model

class Tag extends Model
{
    public function taggables()
    {
        return $this->morphedByMany(Post::class, 'taggable')
                    ->morphedByMany(Video::class, 'taggable');
    }
}

Post Model

class Post extends Model
{
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

Video Model

class Video extends Model
{
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

Get All Tags for a Post

$post = Post::find(1);

foreach ($post->tags as $tag) {
    echo $tag->name;
}

Get All Tags for a Video

$video = Video::find(1);

foreach ($video->tags as $tag) {
    echo $tag->name;
}

9. Optimize Eloquent for Speed

When working with Laravel’s Eloquent ORM, is to optimize database queries and to minimize resource usage which is essential for improving performance and efficiency. Adding caching to your application is one of the very good ways. A cache is used to store the results of time-consuming tasks like database queries thus reducing the number of database interactions. Hence, it is one of the strategies that help in performance optimization.

 Laravel comes with a very strong caching system that collaborates with several backends such as Redis, Memcached, and file-based caching. The website’s data loading by caching the results of Eloquent queries the database is provided in the process thus speeding things up for the user. Moreover, the code lines of the launch can also include the ones that set the output data repositories to the data from the cache if it is present.

Besides caching, Laravel’s query builder allows you to create complicated queries, therefore, you can retrieve and manipulate data fast and conveniently. These features if properly exploited can lead to a vast improvement in your application’s performance and scalability which implies seamless operations for the user.

Summary 

Laravel’s Eloquent ORM not only makes database interactions easier, but it also needs to be optimized for performance and efficiency. The main approaches are eager loading to solve the N+1 query problem, primary key selection for minimizing query size, and using either chunking or cursor() for large data.

Caching becomes a very powerful mechanism for database load reduction. Laravel provides a very adaptable cache system and leverages backends like Redis, Memcached, and file-based storage. Caching of query results not only reduces the number of repeated database hits but also makes responses faster.

The query builder and raw SQL in Laravel can be used to do three things: indexing frequently queried columns, batch operations for inserts/updates, and constructing efficient queries in the first place; hence performance is improved. Polymorphic relations are one of the high-end approaches that optimize structures of complex data, meanwhile tools like Laravel Telescope can perform profiling and queries debugging.

The combination of the above methods guarantees resource usage optimization, as well as faster data retrieval and scalability, which, in turn, enables Laravel applications to offer a hiccup-free, high-speed experience.

Share.
Leave A Reply

Exit mobile version