Eloquent is Laravel's built-in ORM (Object-Relational Mapper) that provides a simple and expressive way to interact with a database. It follows the Active Record pattern, where each model corresponds to a database table, and each instance of a model represents a single row in that table.
This article covers the following:
Creating and using Eloquent models
Defining and using relationships (One-to-One, One-to-Many, Many-to-Many, Has-One-Through, Has-Many-Through, and Polymorphic Relationships)
Querying related data
Best practices
1. Creating and Using Eloquent Models
To create a new model in Laravel, use the Artisan command:
php artisan make:model Product
This command creates a Product.php file inside the app/Models directory (Laravel 8+). If using Laravel 7 or earlier, it will be in app/.
A typical Eloquent model looks like this:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
use HasFactory;
protected $fillable = ['name', 'price', 'description'];
}
Basic CRUD Operations
When a model is created as described above, it can be used to handle basic operations in your application which we often term as CRUD meaning Create a record, Retrieving records, Updating a record, and Deleting a record.
- Creating a Record
$product = Product::create([
'name' => 'Laptop',
'price' => 1500,
'description' => 'High-performance laptop'
]);
- Retrieving Records
$products = Product::all(); // Get all products
$product = Product::find(1); // Find by ID, it is usually one record
$product = Product::where('name', 'Laptop')->first();
- Updating a Record
$product = Product::find(1);
$product->price = 1700;
$product->save();
- Deleting a Record
$product->delete();
Product::destroy(1); // Delete by ID
2. Defining and Using Relationships
- One-to-One Relationship
In this relationship, one entity is directly related to another entity. Entity in this case, an entity is a model record, say a User record would have a one-to-one-relationship with a Profile model record.
Example: User and Profile
app/Models/User.php
class User extends Model
{
public function profile()
{
return $this->hasOne(Profile::class);
}
}
app/Models/Profile.php
class Profile extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
Fetching user profile:
To retrieve a user record, include the following code in one of the methods in the controller class created to handle user modules which typical should be created in app/Http/Controller/UserController.php
, although it can be used in any class method.
php artisan make:controller UserController
open the file created in app/Http/Controller/UserController.php
, add the following code. you can change the method name to what you prefer, but use a name that clearly describes what the method does.
public function findUserProfile()
{
$user = User::find(1); // 1 is the user ID
$profile = $user->profile;
}
- One-to-Many Relationship
In this relationship, one entity is related to multiple entities. Meaning, for instance, a specific post in the Post model would have or own multiple comments in the Comment Model (remember that a model is attached to a single Database table).
Example: Post and Comments
class Post extends Model
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
class Comment extends Model
{
public function post()
{
return $this->belongsTo(Post::class);
}
}
Fetching comments for a post: To retrieve comment records for a specific post, include the following code in one of the methods in the controller class which should be created to handle Post modules typical as app/Http/Controller/PostController.php
, although it can be used in any class.
php artisan make:controller PostController
open the file created in app/Http/Controller/UserController.php
, add the following code. you can change the method name to what you prefer, but use a name that clearly describes what the method does.
public function findPostComment()
{
$post = Post::find(1); // 1 is the post ID
$comments = $post->comments;
}
- Many-to-Many Relationship
Many entities are related to many other entities. A user can have many roles and a role can be assigned to many users. For instance, a user can have both Admin role and and HR role.
Example: Users and Roles
class User extends Model
{
// other methods can be at the top or below
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
class Role extends Model
{
public function users()
{
return $this->belongsToMany(User::class);
}
}
Assigning a role to a user: in your controller method, you can assign a role to a user like this
// assign a role using role Id to a user
$user->roles()->attach($roleId);
- Has-One-Through Relationship
A relationship between two models through an intermediate model. This is useful when you need to access a related model that is connected through another model.
Example: Mechanic → Car → Owner
In this scenario, a mechanic services a car, and each car has one owner. Instead of defining two separate relationships, we can use a has-one-through relationship to access the owner directly from the mechanic.
class Mechanic extends Model
{
public function owner()
{
return $this->hasOneThrough(Owner::class, Car::class);
}
}
This allows you to fetch an owner directly from a mechanic:
$mechanic = Mechanic::find(1);
$owner = $mechanic->owner;
- Has-Many-Through Relationship
A single model has many related models through an intermediate model. This is useful when a model is indirectly related to another model.
Example: Country → Users → Posts
A country has many users, and each user has many posts. Instead of fetching users first and then fetching their posts, we can define a has-many-through relationship.
class Country extends Model
{
public function posts()
{
return $this->hasManyThrough(Post::class, User::class);
}
}
Fetching posts from a country directly:
$country = Country::find(1);
$posts = $country->posts;
- Polymorphic Relationships
Allows multiple models to share the same relationship, meaning different models can be associated with a single model type.
Example: Comments on Posts and Videos
Both posts and videos can have comments, so we use a polymorphic relationship.
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}
class Post extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
class Video extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
This allows us to fetch comments on a post or video:
$post = Post::find(1);
$comments = $post->comments;
$video = Video::find(1);
$comments = $video->comments;
Saving a polymorphic comment:
$post->comments()->create(['body' => 'Great post!']);
3. Querying Related Data
Eloquent provides powerful methods to retrieve related data efficiently.
Eager Loading
Preload related data to optimize queries.
$users = User::with('profile')->get();
Lazy Loading
Loads related data only when accessed.
$user = User::find(1);
$profile = $user->profile;
Constraining Eager Loading
You are able to give a condition to what relationship you want to be eager loaded on your model.
$users = User::with(['posts' => function ($query) {
$query->where('status', 'published');
}])->get();
4. Best Practices
Use fillable or guarded to prevent mass assignment vulnerabilities.
Use eager loading to optimize database queries and reduce N+1 query issues.
Follow naming conventions. Eloquent assumes table names and foreign keys based on model names. table name should be plural, model name should singular, foreign fields are in snake case, like
user_id
Use relationships instead of raw joins for cleaner and maintainable code.
Conclusion
Eloquent ORM in Laravel simplifies database interactions by providing an intuitive syntax for working with models and relationships. Mastering Eloquent will help you write efficient, maintainable, and scalable Laravel applications.
Top comments (0)