Eloquent ORM

Object-Relational Mapping in Laravel

graph TD A[Eloquent Model] --> B[Database Table] A --> C[Relationships] A --> D[Query Builder] A --> E[Accessors/Mutators] A --> F[Events] A --> G[Scopes] A --> H[Soft Deletes] I[Active Record] --> A J[ORM Layer] --> A

Eloquent ORM is a powerful and simple ORM for working with database in Laravel. This ORM uses Active Record pattern and allows you to work with database tables in an object-oriented way.


Main Eloquent Features:


  • <strong>Active Record Pattern</strong>: Each Model represents a row in database table
  • <strong>Relationships</strong>: Defining relationships between models simply
  • <strong>Query Builder</strong>: Using fluent query builder for complex queries
  • <strong>Mass Assignment Protection</strong>: Protection against mass assignment vulnerabilities
  • <strong>Accessors &amp; Mutators</strong>: Transforming data when reading and writing
  • <strong>Events</strong>: Lifecycle events for hooks
  • <strong>Scopes</strong>: Query scopes for reusable queries
  • <strong>Soft Deletes</strong>: Soft deletion without actually deleting from database
  • <strong>Timestamps</strong>: Automatic management of created_at and updated_at
  • <strong>Casting</strong>: Automatic type conversion
  • <strong>Pagination</strong>: Built-in pagination
  • <strong>Eager Loading</strong>: Preventing N+1 query problem

Benefits of Eloquent:


  • Clean and readable code
  • Better security with mass assignment protection
  • Easy work with relationships
  • Type safety with casting
  • Performance optimization with eager loading
  • Better developer experience

Examples

Creating Model

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $table = 'users';
    protected $fillable = ['name', 'email', 'password'];
    protected $hidden = ['password', 'remember_token'];
    protected $casts = [
        'email_verified_at' => 'datetime',
        'is_active' => 'boolean'
    ];
}

A simple Model that defines table and fillable fields.

CRUD Operations

// Create
$user = User::create([
    'name' => 'John Doe',
    'email' => 'john@example.com'
]);

// Read
$user = User::find(1);
$users = User::all();
$user = User::where('email', 'john@example.com')->first();

// Update
$user->name = 'Jane Doe';
$user->save();

// Or
$user->update(['name' => 'Jane Doe']);

// Delete
$user->delete();

// Or
User::destroy(1);

CRUD operations with Eloquent.

Query Builder Integration

// Eloquent uses Query Builder
$users = User::where('active', true)
    ->where('age', '>', 18)
    ->orderBy('name')
    ->limit(10)
    ->get();

// Aggregates
$count = User::where('active', true)->count();
$maxAge = User::max('age');
$avgAge = User::avg('age');

// Chaining
$users = User::query()
    ->where('active', true)
    ->orWhere('verified', true)
    ->get();

Using Query Builder with Eloquent.

Mass Assignment

// Fillable (allowed)
class User extends Model
{
    protected $fillable = ['name', 'email'];
}

// Guarded (blocked)
class User extends Model
{
    protected $guarded = ['id', 'is_admin'];
}

// Usage
User::create(['name' => 'John', 'email' => 'john@example.com']);

// Force fill (bypass protection)
$user->forceFill(['is_admin' => true]);

Mass assignment protection with fillable and guarded.

Timestamps

// Automatic timestamps
class User extends Model
{
    // created_at and updated_at are managed automatically
}

// Disable timestamps
class User extends Model
{
    public $timestamps = false;
}

// Custom timestamp names
class User extends Model
{
    const CREATED_AT = 'created_date';
    const UPDATED_AT = 'modified_date';
}

// Touch parent timestamps
$post->user->touch();

Managing timestamps in Eloquent.

Model Events

<?php

class User extends Model
{
    protected static function booted()
    {
        static::creating(function ($user) {
            // Before create
        });
        
        static::created(function ($user) {
            // After create
        });
        
        static::updating(function ($user) {
            // Before update
        });
        
        static::deleting(function ($user) {
            // Before delete
        });
    }
}

Model events for lifecycle hooks.

Pagination

// Simple pagination
$users = User::paginate(15);

// With query string
$users = User::paginate(15)->withQueryString();

// Cursor pagination (for large datasets)
$users = User::cursorPaginate(15);

// Simple pagination (prev/next only)
$users = User::simplePaginate(15);

// In view
{{ $users->links() }}

// Custom pagination view
{{ $users->links('custom.pagination') }}

Pagination with Eloquent.

Chunking

// Process large datasets in chunks
User::chunk(100, function ($users) {
    foreach ($users as $user) {
        // Process user
    }
});

// Chunk by ID (more efficient)
User::chunkById(100, function ($users) {
    foreach ($users as $user) {
        // Process user
    }
});

// Lazy loading (memory efficient)
foreach (User::lazy() as $user) {
    // Process user
}

Chunking for processing large datasets.

Use Cases

  • Creating and managing database records
  • Defining relationships between models
  • Query building with fluent interface
  • Data transformation with accessors/mutators
  • Event handling for business logic
  • Pagination and chunking for large datasets

Common Mistakes

  • N+1 query problem with relationships
  • Not using eager loading
  • Mass assignment vulnerabilities
  • Using all() for large datasets
  • Forgetting indexes for foreign keys
  • Not using transactions for multiple operations

Best Practices

  • Use eager loading for relationships
  • Use fillable or guarded for mass assignment protection
  • Use indexes for foreign keys
  • Use transactions for multiple operations
  • Use chunking for large datasets
  • Use scopes for reusable queries
  • Use model events for business logic

Edge Cases

  • Very large datasets requiring chunking
  • Complex relationships with multiple levels
  • Polymorphic relationships
  • Model events with circular dependencies
  • Mass assignment with nested data
  • Timestamps in different timezones

Performance Notes

  • Eager loading can solve N+1 problem
  • Indexes for foreign keys are important
  • Chunking for large datasets is essential
  • Query caching can improve performance
  • Using select() for specific columns
  • Lazy loading can save memory

Security Notes

  • Always use fillable or guarded
  • Use forceFill() only for trusted data
  • Ensure sensitive fields are in hidden
  • Don't use mass assignment for user input
  • Ensure relationships are properly authorized

Interview Points

  • What is Eloquent ORM and how does it work?
  • What is the difference between fillable and guarded?
  • What is N+1 query problem and how is it solved?
  • What are model events and when are they used?
  • What is the difference between chunk() and lazy()?
  • What are the benefits of using Eloquent?

Version Notes

  • Laravel 11.x: Improved performance in Eloquent queries
  • Laravel 11.x: Better support for cursor pagination
  • Laravel 10.x: Improved eager loading
  • Laravel 9.x: Improved model events