
December 05, 2025
5 min read
Table of Contents
Laravel’s Eloquent ORM remains one of the most expressive and powerful ActiveRecord implementations in modern PHP frameworks. But as applications grow — especially large SaaS platforms, enterprise systems, or domain-driven architectures — developers quickly discover that basic Eloquent usage is not enough.
To build complex applications, you must master:
Advanced relationship handling
Efficient query optimization
Polymorphic structures
Data pipelines
DTO mapping
Model events & observers
Attribute casting & value objects
Query customization using macros
Multi-tenancy considerations
Repository + domain patterns
Chunking, cursoring, caching strategies
Raw expressions and subqueries
Aggregate and analytical queries
This guide dives deeply into advanced Eloquent techniques used by senior Laravel engineers when handling high-performance, domain-rich, multi-layered applications.
1. Advanced Relationship Techniques
Eloquent relationships become extremely powerful when you use them beyond the basics.
a. Using Subqueries Inside Relationships
Example: Include latest order on each customer:
$customers = Customer::addSelect([
'latest_order_total' => Order::select('total')
->whereColumn('customer_id', 'customers.id')
->latest()
->limit(1)
])->get();
This prevents N+1 problems without eager loading.
b. Constraining Eager Loads
Load only active subscriptions:
User::with(['subscriptions' => function ($q) {
$q->where('status', 'active');
}])->get();
c. Loading Relationship Counts With Conditions
User::withCount(['orders as high_value_orders_count' => function ($q) {
$q->where('total', '>', 500);
}])->get();
This is essential in dashboards and analytics.
2. Polymorphic Relationship Power
Polymorphic relations become necessary in large systems where multiple entities share common features.
Example: Comments on Posts, Videos, Events
public function commentable()
{
return $this->morphTo();
}
Advanced polymorphic usage includes:
Polymorphic many-to-many for tagging
Polymorphic nested structures
Polymorphic pivot tables
Polymorphic Many-to-Many Tagging System
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
This allows one tagging table for dozens of entities.
3. Using Custom Pivot Models
Pivot tables often need additional fields like:
status
role
metadata
permission levels
Define a custom Pivot model:
class Membership extends Pivot
{
protected $casts = [
'joined_at' => 'datetime',
'metadata' => 'array',
];
}
Attach to relationship:
public function memberships()
{
return $this->belongsToMany(Team::class)
->using(Membership::class)
->withTimestamps();
}
4. Value Object Casting & Custom Casts
Large applications benefit from rich data types, not just primitive values.
Example: Casting a Money value object:
class MoneyCast implements CastsAttributes {
public function get($model, $key, $value) {
return new Money($value);
}
public function set($model, $key, $value) {
return $value->amount();
}
}
Model:
protected $casts = [
'balance' => MoneyCast::class
];
This yields cleaner domain-driven code.
5. Attribute Transformers (Accessors & Mutators)
Eloquent's attribute methods help structure domain rules.
Example: Encrypting sensitive fields:
protected function ssn(): Attribute
{
return Attribute::make(
get: fn ($value) => decrypt($value),
set: fn ($value) => encrypt($value)
);
}
6. Query Scopes for Cleaner Query Logic
Example: Shared logic for active tenants:
public function scopeActive($query)
{
return $query->where('status', 'active');
}
Chainable:
Tenant::active()->where('plan', 'pro')->get();
7. Repository Pattern Done Properly
In large domain-driven architectures, isolate business logic from Eloquent models.
Example:
class UserRepository {
public function findWithOrders($id) {
return User::with('orders')->findOrFail($id);
}
}
Best used in enterprise layers, DDD, microservices, and SaaS.
8. Avoiding N+1 Queries: Advanced Techniques
a. Using loadMissing() to conditionally load relationships
$user->loadMissing('profile');
b. Using lazy() & cursor() for large datasets
Efficient memory handling:
foreach (User::cursor() as $user) {
//
}
c. Using chunkById() for scalable batch processing
User::chunkById(100, function ($users) {
//
});
9. Raw Expressions & Analytical Queries
For reporting-heavy applications:
Using DB::raw in a Select
User::select(
'name',
DB::raw('COUNT(*) OVER () as total_users')
)->get();
Using Subqueries for Ranking
User::select(
'name',
DB::raw('row_number() over(order by points desc) as rank')
)->get();
10. JSON Columns & Advanced Querying
Modern databases like MySQL 8/PostgreSQL support JSON querying.
Example: Querying inside JSON:
User::where('settings->theme', 'dark')->get();
Updating JSON keys:
$user->update([
'settings->notifications->email' => false
]);
JSON is essential for dynamic schemas in SaaS apps.
11. Model Observers for Domain Events
Observers centralize lifecycle logic.
Examples:
Automatically creating profile when user registers
Generating tenant resources
Syncing logs to external services
class UserObserver
{
public function created(User $user)
{
Profile::create(['user_id' => $user->id]);
}
}
Register:
User::observe(UserObserver::class);
Observers enforce consistency across all models.
12. Model Events + Queues for Heavy Lifting
Example: Processing image uploads asynchronously:
protected static function booted()
{
static::created(fn($post) =>
ProcessPostImages::dispatch($post)
);
}
Large SaaS apps rely heavily on this architecture.
13. Eloquent Macros for Custom ORM Methods
Extend Eloquent globally:
Builder::macro('whereLike', function ($column, $value) {
return $this->where($column, 'LIKE', "%{$value}%");
});
Usage:
User::whereLike('email', '@gmail.com')->get();
Macros help enforce organization-wide query patterns.
14. Using Eloquent with Multi-Tenancy
Isolation patterns:
Global Scope:
protected static function booted()
{
static::addGlobalScope('tenant', function (Builder $builder) {
$builder->where('tenant_id', tenant('id'));
});
}
OR using stancl/tenancy model separation:
CentralModelTenantModel
Allows per-tenant DB isolation.
15. Caching Eloquent Queries: Best Practices
Never cache full Eloquent models with relationships blindly.
Cache primitives:
Cache::remember("user:{$id}", 3600, fn() =>
User::select('id','name','email')->find($id)
);
Cache heavy computations:
Cache::remember('reports:monthly', 7200, fn() =>
ReportService::generate()
);
16. Pipelines + Eloquent = Clean Query Builders
Example: Apply filters dynamically:
app(Pipeline::class)
->send(User::query())
->through([
Filters\Active::class,
Filters\Role::class,
Filters\DateRange::class
])
->thenReturn()
->paginate();
This pattern powers advanced admin dashboards and marketplaces.
Conclusion
Mastering advanced Eloquent concepts is essential when building large-scale, data-heavy, domain-driven, multi-tenant, or enterprise Laravel applications.
Eloquent is far more than a simple ORM — when used properly, it becomes a powerful domain modeling tool that handles:
complex relational data
high-performance queries
structured domain logic
scalable architecture patterns
expressive business rules
To continue mastering high-level Laravel architecture, explore more guides from an expert web developer in Nepal who specializes in scalable backend engineering and SaaS systems.

