Models

Creating and using Eloquent Models

graph TD A[Eloquent Model] --> B[Database Table] A --> C[Mass Assignment Protection] A --> D[Timestamps] A --> E[Soft Deletes] A --> F[Casting] A --> G[Accessors/Mutators] A --> H[Scopes] A --> I[Relationships] A --> J[Events] K[Active Record Pattern] --> A L[ORM Layer] --> A

Eloquent Models are PHP classes where each represents a table in the database and uses Active Record pattern. Each instance of Model represents a row in database table.


Main Model Features:


  • <strong>Mass Assignment Protection</strong>: Protection against accidentally assigning sensitive fields with <code>$fillable</code> and <code>$guarded</code>
  • <strong>Timestamps</strong>: Automatic management of <code>created_at</code> and <code>updated_at</code>
  • <strong>Soft Deletes</strong>: Soft deletion with <code>SoftDeletes</code> trait
  • <strong>Casting</strong>: Automatic data type conversion when reading and writing
  • <strong>Accessors &amp; Mutators</strong>: Transforming and accessing attributes before reading or writing
  • <strong>Scopes</strong>: Query scopes for reusable queries
  • <strong>Relationships</strong>: Defining relationships between models
  • <strong>Events</strong>: Lifecycle events for hooks
  • <strong>Observers</strong>: Model observers for event handling
  • <strong>Factories</strong>: Model factories for test data
  • <strong>Pagination</strong>: Built-in pagination support

Model Structure:


Each Model must extend Illuminate\Database\Eloquent\Model. Laravel automatically infers table name from class name (plural form), but you can override it with $table property.


Convention over Configuration:


Laravel uses conventions to reduce need for configuration:


  • Table name: plural form of model name (User → users)
  • Primary key: <code>id</code>
  • Foreign key: <code>{model}_id</code> (User → user_id)
  • Timestamps: <code>created_at</code>, <code>updated_at</code>
  • Soft delete: <code>deleted_at</code>

Model Lifecycle:


Models have lifecycle events that you can hook into:


  • <code>creating</code>, <code>created</code> - before and after create
  • <code>updating</code>, <code>updated</code> - before and after update
  • <code>saving</code>, <code>saved</code> - before and after save (create or update)
  • <code>deleting</code>, <code>deleted</code> - before and after delete
  • <code>restoring</code>, <code>restored</code> - before and after restore (soft delete)

Best Practices:


  • Use <code>$fillable</code> or <code>$guarded</code> for mass assignment protection
  • Use <code>$hidden</code> for fields that shouldn&#039;t be shown in JSON
  • Use <code>$casts</code> for type casting
  • Use relationships for working with related data
  • Use scopes for reusable queries

Examples

Basic 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 basic Model with fillable, hidden and casts defined.

Model with Relationships

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
    
    public function profile()
    {
        return $this->hasOne(Profile::class);
    }
    
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
}

// Usage
$user = User::find(1);
$posts = $user->posts;
$profile = $user->profile;
$roles = $user->roles;

A Model with various relationships defined.

Model with Scopes

<?php

class Post extends Model
{
    public function scopePublished($query)
    {
        return $query->where('status', 'published');
    }
    
    public function scopeByAuthor($query, $authorId)
    {
        return $query->where('author_id', $authorId);
    }
    
    protected static function booted()
    {
        static::addGlobalScope('active', function ($query) {
            $query->where('active', 1);
        });
    }
}

// Usage
$posts = Post::published()->byAuthor(1)->get();

Model with local and global scopes.

Model Events

<?php

class User extends Model
{
    protected static function booted()
    {
        static::creating(function ($user) {
            $user->uuid = Str::uuid();
        });
        
        static::created(function ($user) {
            // Send welcome email
            Mail::to($user->email)->send(new WelcomeMail($user));
        });
        
        static::updating(function ($user) {
            // Log changes
            Log::info('User updated', ['user_id' => $user->id]);
        });
    }
}

Using model events for lifecycle hooks.

Model with Accessors and Mutators

<?php

class User extends Model
{
    public function getFullNameAttribute()
    {
        return "{$this->first_name} {$this->last_name}";
    }
    
    public function setPasswordAttribute($value)
    {
        $this->attributes['password'] = Hash::make($value);
    }
    
    public function getIsAdminAttribute()
    {
        return $this->role === 'admin';
    }
}

// Usage
$user = User::find(1);
echo $user->full_name; // Accessor
$user->password = 'secret'; // Mutator
echo $user->is_admin; // Accessor

Using accessors and mutators to transform data.

Model with Soft Deletes

<?php

use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes;
    
    protected $dates = ['deleted_at'];
}

// Usage
$post->delete(); // Soft delete
$post->restore(); // Restore
$post->forceDelete(); // Permanent delete

// Query deleted records
$deletedPosts = Post::onlyTrashed()->get();
$allPosts = Post::withTrashed()->get();

Using SoftDeletes trait for soft deletion.

Custom Primary Key

<?php

class User extends Model
{
    protected $primaryKey = 'uuid';
    public $incrementing = false;
    protected $keyType = 'string';
}

// Or with composite key
class UserRole extends Model
{
    protected $primaryKey = ['user_id', 'role_id'];
    public $incrementing = false;
}

Defining custom primary key for model.

Use Cases

  • Representing database tables in object-oriented way
  • Defining relationships between entities
  • Mass assignment protection for security
  • Data transformation with accessors/mutators
  • Query building with scopes
  • Lifecycle management with events
  • Soft deletion for data retention

Common Mistakes

  • Forgetting to define fillable or guarded causing mass assignment vulnerability
  • Using all() for large datasets causing memory problems
  • N+1 query problem with relationships
  • Forgetting return statement in scope methods
  • Using model events for complex business logic
  • Not using eager loading for relationships

Best Practices

  • Always define fillable or guarded
  • Use eager loading for relationships
  • Use scopes for reusable queries
  • Use model events for simple hooks
  • Use accessors/mutators for data transformation
  • Use factories for test data
  • Keep model logic simple and put business logic in service layer

Edge Cases

  • Models with composite primary keys
  • Models with custom table names
  • Models with multiple database connections
  • Model events with circular dependencies
  • Soft deletes with relationships
  • Mass assignment with nested data
  • Models with polymorphic relationships

Performance Notes

  • Use eager loading to prevent N+1 queries
  • Use select() for selecting specific columns
  • Use chunking for large datasets
  • Use indexes for foreign keys
  • Use query caching for frequently accessed data
  • Use lazy loading for memory efficiency

Security Notes

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

Interview Points

  • What is Eloquent Model and how does it work?
  • What is the difference between fillable and guarded?
  • What are model events and when are they used?
  • What is the difference between accessor and mutator?
  • How can you define custom primary key?
  • What are soft deletes and how do they work?

Version Notes

  • Laravel 11.x: Improved performance in model operations
  • Laravel 11.x: Better support for model events
  • Laravel 10.x: Improved eager loading
  • Laravel 9.x: Improved model factories