Use when writing Eloquent models, relationships, scopes, or queries via Model:: — 'fetch users with their orders'. NOT for PHPStan output, non-Eloquent services, or raw SQL questions.
Scanned 6/5/2026
Install to Claude Code
npx -y skills add event4u-app/agent-config --skill eloquent --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Eloquent?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/event4u-app-eloquent)More formats (shields.io, HTML) on the badges page.
---
model_tier: medium
name: eloquent
description: "Use when writing Eloquent models, relationships, scopes, or queries via Model:: — 'fetch users with their orders'. NOT for PHPStan output, non-Eloquent services, or raw SQL questions."
personas:
- eloquent-tamer
domain: engineering
workspaces:
- engineering
packs:
- laravel
trust:
level: professional
install:
default: false
removable: true
---
# eloquent
## When to use
Use when creating/modifying Eloquent models, relationships, scopes, or writing database queries.
Do NOT use when:
- Schema design or query optimization (use `database` skill)
- Creating migrations only (use `laravel-migration` skill)
## Procedure: Create or modify a model
### Step 0: Inspect
1. Check existing models — match property declarations, cast patterns, relationship style, scope naming.
2. Check for repositories — some projects use repository interfaces.
3. Understand the schema — check migrations for column names, types, constraints.
4. Check for multi-tenancy — which `$connection` to use?
### Step 1: Read attribute access style
Read `eloquent.access_style` from `.agent-settings.yml`. Default: `getters_setters`.
| Value | Inside model | Outside model |
|---|---|---|
| `getters_setters` | `getAttribute()` / `setAttribute()` | Typed getters/setters |
| `get_attribute` | `getAttribute()` / `setAttribute()` | Same |
| `magic_properties` | `$this->column` | `$model->column` |
→ See guideline `php/eloquent.md` and `php-coding` rule for full conventions.
### Step 2: Build the model
1. Set `$connection`, `$table`, `$fillable`/`$guarded`, `$casts`, `$attributes` (defaults).
2. Add typed getters + fluent setters for each attribute (if `getters_setters` style).
3. Add relationship getter above each relationship method.
4. Add scopes for reusable query constraints.
5. Register Observer via `#[ObservedBy]` — never use `booted()`.
### Step 3: Write queries
- Always eager load relationships accessed in loops: `->with(['customer'])`.
- Always paginate list queries: `->paginate(15)`.
- Use `exists()` over `count() > 0`.
- Use `chunk()` / `lazy()` for large datasets.
- Constrain eager loads when only a subset is needed.
## Conventions
→ See guideline `php/eloquent.md` for getter/setter examples, relationship getters, observers, casts.
→ See guideline `php/database.md` for indexing, transactions, migrations.
### Validate
- Run PHPStan on model — must pass.
- Verify no N+1: check that all relationship access in loops uses eager loading.
- Confirm typed getters exist for every relationship.
- Run affected tests — must pass.
## Output format
1. Model class with typed getters/setters, relationships, and observer
2. Migration file if schema changes are needed
## Gotcha
- Never access relationships via magic properties — always use typed getter.
- N+1 queries are the #1 performance issue — always eager load.
- `getAttribute()` returns `mixed` — cast or type-check the result.
- `$model->save()` can silently fail without fillable/guarded config.
## Do NOT
- Do NOT put business logic in models — delegate to services.
- Do NOT access relationships in loops without eager loading.
- Do NOT use `Model::all()` without pagination on list endpoints.
- Do NOT use `booted()` for lifecycle hooks — use Observers with `#[ObservedBy]`.
## Auto-trigger keywords
- Eloquent
- model
- relationship
- scope
- accessor
- mutator
No comments yet. Be the first to comment!