Laravel's Eloquent ORM is a powerful tool that simplifies database interactions through an elegant ActiveRecord implementation. Whether you're a seasoned Laravel developer or just starting, mastering Eloquent can greatly enhance your ability to build robust, efficient, and maintainable applications.
This guide will take you through the core concepts, advanced techniques, and best practices to help you unlock the full potential of Eloquent ORM in Laravel.
Eloquent ORM (Object-Relational Mapping) is Laravel’s built-in ORM that provides a simple and expressive way to interact with your database. With Eloquent, each database table is associated with a corresponding "Model" in your Laravel application, and you can perform database operations using intuitive methods.
To use Eloquent, you need to define a model for each database table. You can create a model using the Artisan CLI:
php artisan make:model Post
By default, the Post
model will interact with the posts
table in the database.
Here’s what a basic Eloquent model might look like:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = ['title', 'content', 'status'];
}
Eloquent simplifies CRUD (Create, Read, Update, Delete) operations. Here's how you can perform them:
$post = new Post();
$post->title = 'Laravel Eloquent Guide';
$post->content = 'Mastering Eloquent ORM in Laravel.';
$post->status = 'published';
$post->save();
Alternatively, use mass assignment:
Post::create([
'title' => 'Laravel Eloquent Guide',
'content' => 'Mastering Eloquent ORM in Laravel.',
'status' => 'published',
]);
$posts = Post::all(); // Fetch all records
$post = Post::find(1); // Fetch a single record by ID
$publishedPosts = Post::where('status', 'published')->get(); // Conditional fetch
$post = Post::find(1);
$post->title = 'Updated Title';
$post->save();
Or with mass assignment:
Post::where('id', 1)->update(['title' => 'Updated Title']);
$post = Post::find(1);
$post->delete();
Or delete directly:
Post::destroy(1);
Eloquent makes it easy to define relationships between models, such as One-to-One, One-to-Many, and Many-to-Many.
class User extends Model
{
public function phone()
{
return $this->hasOne(Phone::class);
}
}
class Post extends Model
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
class User extends Model
{
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
Eager loading solves the N+1 query problem by loading related data in a single query.
$posts = Post::with('comments')->get();
Scopes allow you to define common queries directly in your model.
class Post extends Model
{
protected static function booted()
{
static::addGlobalScope('published', function ($query) {
$query->where('status', 'published');
});
}
}
class Post extends Model
{
public function scopePublished($query)
{
return $query->where('status', 'published');
}
}
$posts = Post::published()->get();
Accessors format attributes when retrieved, and mutators format attributes before they’re saved.
class Post extends Model
{
public function getTitleAttribute($value)
{
return ucfirst($value);
}
}
class Post extends Model
{
public function setTitleAttribute($value)
{
$this->attributes['title'] = strtolower($value);
}
}
Eloquent allows you to cast attributes to specific data types.
class Post extends Model
{
protected $casts = [
'is_published' => 'boolean',
];
}
Chunking: Process large datasets in chunks to save memory.
Post::chunk(100, function ($posts) {
foreach ($posts as $post) {
// Process each post
}
});
Lazy Eager Loading: Dynamically load relationships when needed.
$posts = Post::all();
$posts->load('comments');
Indexes: Ensure frequently queried fields are indexed in your database.
Select Specific Columns: Avoid fetching unnecessary columns.
$posts = Post::select('id', 'title')->get();
$fillable
or $guarded
to protect your models from mass assignment vulnerabilities.query scopes
to make your queries reusable and concise.