Laravel Eloquent ORM
Agent Workflow (MANDATORY)
Before ANY implementation, use TeamCreate to spawn 3 agents:
- fuse-ai-pilot:explore-codebase - Check existing models, relationships
- fuse-ai-pilot:research-expert - Verify latest Eloquent docs via Context7
- mcp__context7__query-docs - Query specific patterns (casts, scopes)
After implementation, run fuse-ai-pilot:sniper for validation.
Overview
Eloquent is Laravel's ActiveRecord ORM implementation. Models represent database tables and provide a fluent interface for queries.
| Feature |
Purpose |
| Models |
Table representation with attributes |
| Relationships |
Define connections between models |
| Query Scopes |
Reusable query constraints |
| Casts |
Attribute type conversion |
| Events/Observers |
React to model lifecycle |
| Factories |
Generate test data |
Critical Rules
- Always eager load relationships - Prevent N+1 queries
- Use scopes for reusable queries - Don't repeat WHERE clauses
- Cast attributes properly - Type safety for dates, arrays, enums
- No business logic in models - Keep models slim
- Use factories for testing - Never hardcode test data
Decision Guide
Relationship Type
What's the cardinality?
├── One-to-One → hasOne / belongsTo
├── One-to-Many → hasMany / belongsTo
├── Many-to-Many → belongsToMany (pivot table)
├── Through another → hasOneThrough / hasManyThrough
└── Polymorphic?
├── One-to-One → morphOne / morphTo
├── One-to-Many → morphMany / morphTo
└── Many-to-Many → morphToMany / morphedByMany
Performance Issue
What's the problem?
├── Too many queries → Eager loading (with)
├── Memory exhaustion → chunk() or cursor()
├── Slow queries → Add indexes, select columns
├── Repeated queries → Cache results
└── Large inserts → Batch operations
Reference Guide
Concepts (WHY & Architecture)
| Topic |
Reference |
When to Consult |
| Models |
models.md |
Model config, fillable, conventions |
| Basic Relations |
relationships-basic.md |
HasOne, HasMany, BelongsTo |
| Many-to-Many |
relationships-many-to-many.md |
Pivot tables, attach/sync |
| Advanced Relations |
relationships-advanced.md |
Through, dynamic relations |
| Polymorphic |
relationships-polymorphic.md |
MorphTo, MorphMany |
| Eager Loading |
eager-loading.md |
N+1 prevention, with() |
| Scopes |
scopes.md |
Local, global, dynamic |
| Casts |
casts.md |
Type casting, custom casts |
| Accessors/Mutators |
accessors-mutators.md |
Attribute transformation |
| Events/Observers |
events-observers.md |
Lifecycle hooks |
| Soft Deletes |
soft-deletes.md |
Recoverable deletion |
| Collections |
collections.md |
Eloquent collection methods |
| Serialization |
serialization.md |
toArray, toJson, hidden |
| Factories |
factories.md |
Test data generation |
| Performance |
performance.md |
Optimization techniques |
| API Resources |
resources.md |
JSON transformation |
| Transactions |
transactions.md |
Atomic operations, rollback |
| Pagination |
pagination.md |
paginate, cursor, simplePaginate |
| Aggregates |
aggregates.md |
count, sum, withCount, exists |
| Batch Operations |
batch-operations.md |
insert, upsert, mass update |
| Query Debugging |
query-debugging.md |
toSql, dd, DB::listen |
Templates (Complete Code)
| Template |
When to Use |
| ModelBasic.php.md |
Standard model with scopes |
| ModelRelationships.php.md |
All relationship types |
| ModelCasts.php.md |
Casts and accessors |
| Observer.php.md |
Complete observer |
| Factory.php.md |
Factory with states |
| Resource.php.md |
API resource |
| EagerLoadingExamples.php.md |
N+1 prevention |
Quick Reference
Basic Model
class Post extends Model
{
protected $fillable = ['title', 'content', 'author_id'];
protected function casts(): array
{
return [
'published_at' => 'datetime',
'metadata' => 'array',
];
}
public function author(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
Eager Loading
// ✅ Good - 2 queries
$posts = Post::with('author')->get();
// ❌ Bad - N+1 queries
$posts = Post::all();
foreach ($posts as $post) {
echo $post->author->name;
}
Query Scopes
#[Scope]
protected function published(Builder $query): void
{
$query->whereNotNull('published_at');
}
// Usage: Post::published()->get();
Best Practices
DO
- Use
$fillable for mass assignment protection
- Eager load relationships with
with()
- Use scopes for reusable query logic
- Cast dates, arrays, and enums
- Use factories in tests
DON'T
- Put business logic in models
- Lazy load in loops (N+1)
- Use
$guarded = [] in production
- Query in accessors/mutators
- Forget foreign keys in
with() columns
1---2name: laravel-eloquent-33description: Complete Eloquent ORM - models, relationships, queries, casts, observers, factories. Use when working with database models.4---56# Laravel Eloquent ORM78## Agent Workflow (MANDATORY)910Before ANY implementation, use `TeamCreate` to spawn 3 agents:11121. **fuse-ai-pilot:explore-codebase** - Check existing models, relationships132. **fuse-ai-pilot:research-expert** - Verify latest Eloquent docs via Context7143. **mcp__context7__query-docs** - Query specific patterns (casts, scopes)1516After implementation, run **fuse-ai-pilot:sniper** for validation.1718---1920## Overview2122Eloquent is Laravel's ActiveRecord ORM implementation. Models represent database tables and provide a fluent interface for queries.2324| Feature | Purpose |25|---------|---------|26| **Models** | Table representation with attributes |27| **Relationships** | Define connections between models |28| **Query Scopes** | Reusable query constraints |29| **Casts** | Attribute type conversion |30| **Events/Observers** | React to model lifecycle |31| **Factories** | Generate test data |3233---3435## Critical Rules36371. **Always eager load relationships** - Prevent N+1 queries382. **Use scopes for reusable queries** - Don't repeat WHERE clauses393. **Cast attributes properly** - Type safety for dates, arrays, enums404. **No business logic in models** - Keep models slim415. **Use factories for testing** - Never hardcode test data4243---4445## Decision Guide4647### Relationship Type4849```50What's the cardinality?51├── One-to-One → hasOne / belongsTo52├── One-to-Many → hasMany / belongsTo53├── Many-to-Many → belongsToMany (pivot table)54├── Through another → hasOneThrough / hasManyThrough55└── Polymorphic?56 ├── One-to-One → morphOne / morphTo57 ├── One-to-Many → morphMany / morphTo58 └── Many-to-Many → morphToMany / morphedByMany59```6061### Performance Issue6263```64What's the problem?65├── Too many queries → Eager loading (with)66├── Memory exhaustion → chunk() or cursor()67├── Slow queries → Add indexes, select columns68├── Repeated queries → Cache results69└── Large inserts → Batch operations70```7172---7374## Reference Guide7576### Concepts (WHY & Architecture)7778| Topic | Reference | When to Consult |79|-------|-----------|-----------------|80| **Models** | [models.md](references/models.md) | Model config, fillable, conventions |81| **Basic Relations** | [relationships-basic.md](references/relationships-basic.md) | HasOne, HasMany, BelongsTo |82| **Many-to-Many** | [relationships-many-to-many.md](references/relationships-many-to-many.md) | Pivot tables, attach/sync |83| **Advanced Relations** | [relationships-advanced.md](references/relationships-advanced.md) | Through, dynamic relations |84| **Polymorphic** | [relationships-polymorphic.md](references/relationships-polymorphic.md) | MorphTo, MorphMany |85| **Eager Loading** | [eager-loading.md](references/eager-loading.md) | N+1 prevention, with() |86| **Scopes** | [scopes.md](references/scopes.md) | Local, global, dynamic |87| **Casts** | [casts.md](references/casts.md) | Type casting, custom casts |88| **Accessors/Mutators** | [accessors-mutators.md](references/accessors-mutators.md) | Attribute transformation |89| **Events/Observers** | [events-observers.md](references/events-observers.md) | Lifecycle hooks |90| **Soft Deletes** | [soft-deletes.md](references/soft-deletes.md) | Recoverable deletion |91| **Collections** | [collections.md](references/collections.md) | Eloquent collection methods |92| **Serialization** | [serialization.md](references/serialization.md) | toArray, toJson, hidden |93| **Factories** | [factories.md](references/factories.md) | Test data generation |94| **Performance** | [performance.md](references/performance.md) | Optimization techniques |95| **API Resources** | [resources.md](references/resources.md) | JSON transformation |96| **Transactions** | [transactions.md](references/transactions.md) | Atomic operations, rollback |97| **Pagination** | [pagination.md](references/pagination.md) | paginate, cursor, simplePaginate |98| **Aggregates** | [aggregates.md](references/aggregates.md) | count, sum, withCount, exists |99| **Batch Operations** | [batch-operations.md](references/batch-operations.md) | insert, upsert, mass update |100| **Query Debugging** | [query-debugging.md](references/query-debugging.md) | toSql, dd, DB::listen |101102### Templates (Complete Code)103104| Template | When to Use |105|----------|-------------|106| [ModelBasic.php.md](references/templates/ModelBasic.php.md) | Standard model with scopes |107| [ModelRelationships.php.md](references/templates/ModelRelationships.php.md) | All relationship types |108| [ModelCasts.php.md](references/templates/ModelCasts.php.md) | Casts and accessors |109| [Observer.php.md](references/templates/Observer.php.md) | Complete observer |110| [Factory.php.md](references/templates/Factory.php.md) | Factory with states |111| [Resource.php.md](references/templates/Resource.php.md) | API resource |112| [EagerLoadingExamples.php.md](references/templates/EagerLoadingExamples.php.md) | N+1 prevention |113114---115116## Quick Reference117118### Basic Model119120```php121class Post extends Model122{123 protected $fillable = ['title', 'content', 'author_id'];124125 protected function casts(): array126 {127 return [128 'published_at' => 'datetime',129 'metadata' => 'array',130 ];131 }132133 public function author(): BelongsTo134 {135 return $this->belongsTo(User::class);136 }137}138```139140### Eager Loading141142```php143// ✅ Good - 2 queries144$posts = Post::with('author')->get();145146// ❌ Bad - N+1 queries147$posts = Post::all();148foreach ($posts as $post) {149 echo $post->author->name;150}151```152153### Query Scopes154155```php156#[Scope]157protected function published(Builder $query): void158{159 $query->whereNotNull('published_at');160}161162// Usage: Post::published()->get();163```164165---166167## Best Practices168169### DO170- Use `$fillable` for mass assignment protection171- Eager load relationships with `with()`172- Use scopes for reusable query logic173- Cast dates, arrays, and enums174- Use factories in tests175176### DON'T177- Put business logic in models178- Lazy load in loops (N+1)179- Use `$guarded = []` in production180- Query in accessors/mutators181- Forget foreign keys in `with()` columns