laravel
When to use
Use this skill for all Laravel-specific code generation and editing tasks, especially when working with:
- Controllers
- Form Requests
- Middleware
- Service Providers
- Jobs / Queued Jobs
- Events / Listeners
- Policies / Gates
- Notifications
- Console Commands
- Config, Routing, and Application Structure
This skill extends the base php-coder skill and applies Laravel conventions on top of the project's general PHP rules.
When NOT to use — components without the framework
A DEPENDENCY PROVES A LIBRARY IS AVAILABLE. ONLY THE ENTRY POINT AND THE
ROUTER PROVE WHICH APPLICATION SHAPE IS RUNNING.
`illuminate/*` PACKAGES WITH NO SKELETON MARKER IS A THIRD STATE, AND THIS SKILL
DOES NOT APPLY TO IT.
Laravel ships its ORM, container, collections and HTTP layer as
independently installable packages, usable with no framework present — a
published distribution model, not one consumer's arrangement. An application
built that way has a custom entry point and a custom router. Routing it here
offers a CLI that does not exist, a request-validation primitive that is not
wired, and a routes file that was never there: every suggestion confidently
wrong, and the reason visible only from the entry point.
The probe set, and its cost. A fixed set of filesystem existence checks plus
one manifest read — no directory walk, no content scan, and never re-derived per
session. Any ONE marker present means the framework is real:
| Probe |
Meaning |
artisan |
the console entry point the skeleton writes |
config/app.php |
the skeleton's bootstrap config |
bootstrap/app.php |
the application bootstrap |
illuminate/* in composer.json with none of those markers is
components-without-the-framework. Say so and route away from this skill rather
than answering as though the framework were there.
Implemented deterministically in src/install/detect_php_shape.ts
(detectPhpShape), whose PROBE_PATHS is this table and whose verdict names
what a wrong route would have offered.
Procedure: Write Laravel code
→ First apply the php-coder skill — it handles project docs, module docs, patterns, and quality tools.
Then add these Laravel-specific checks:
- Confirm this is a Laravel app — check whether
artisan exists.
- Inspect app structure — classic Laravel, modules (
app/Modules/), or domain folders.
- Check routes and HTTP flow — understand how requests enter the application and where logic belongs.
- Check test conventions — inspect existing tests in the same domain before writing new code.
Core Laravel principles
- Follow Laravel conventions first unless the project explicitly does otherwise.
- Keep controllers thin — delegate business logic to services/actions.
- Keep Form Requests responsible for validation and authorization.
- Use dependency injection through the container.
- Prefer framework features over custom infrastructure when the built-in solution is sufficient.
- Avoid hidden magic when explicit code is clearer for the project.
- Respect the existing architecture — do not force "pure Laravel" if the project uses modules or service layers.
HTTP layer rules
- Controllers should:
- accept the request
- delegate business logic
- return a response / resource / redirect
- Do not put business logic, calculations, or large data transformations in controllers.
- Use Form Request classes for validation instead of inline controller validation when the request is non-trivial.
- Use route model binding when it improves clarity and matches existing patterns.
- Keep controller actions focused and small.
Validation rules
- Use Form Requests for reusable or non-trivial validation.
- Prefer explicit validation rules over implicit behavior.
- Reuse existing custom rules when available.
- Keep validation close to the HTTP boundary.
- Do not mix validation with persistence or business decisions.
Service layer rules
- Put orchestration and business logic into dedicated services/actions.
- Services should be framework-light when possible.
- A service should have one clear responsibility.
- Prefer constructor injection for dependencies.
- Do not move trivial one-line controller behavior into a service unless the project consistently does that.
Routing rules
- Follow the existing route organization:
routes/web.php
routes/api.php
- module-specific route files
- Keep route definitions readable and grouped logically.
- Use route names consistently.
- Apply middleware explicitly and according to project conventions.
- Do not introduce route patterns that differ from the surrounding code without a good reason.
Response rules
- Use the response style already established in the project:
- Blade views
- JSON responses
- API Resources
- Redirects with flash messages
- For APIs, prefer:
- consistent status codes
- structured JSON payloads
- API Resources when the project uses them
- Do not return raw models directly unless that is already the established project pattern.
Queues, jobs, and async work
- Use Jobs for clearly asynchronous or deferred work.
- Keep Jobs focused on a single responsibility.
- Pass only the data needed by the job.
- Avoid putting excessive domain logic directly into the Job class — delegate to services where appropriate.
- Be mindful of serialization when passing models or objects.
Events and listeners
- Use events for meaningful domain or application events, not for every small action.
- Name events clearly in the past tense when something already happened.
- Keep listeners focused and side-effect oriented.
- Do not introduce event-driven complexity unless it is already part of the project architecture.
Auth, policies, and authorization
- Use Laravel authorization features consistently:
- policies
- gates
- request authorization
- Keep authorization logic out of controllers where possible.
- Reuse existing policies and permission patterns.
- Do not hardcode role checks in multiple places if a policy/gate already exists.
Config and environment
- Read configuration from config files, not directly from
env() outside config files.
- Do not introduce new environment variables unless necessary.
- Reuse existing config structure and naming patterns.
Database interaction
- Prefer Eloquent for normal application data access unless the project uses repositories or query objects.
- Use transactions when multiple writes must succeed or fail together.
- Avoid N+1 problems — eager load when appropriate.
- For heavy data access logic, follow the dedicated
eloquent skill.
Migrations and schema changes
- Keep migrations focused and reversible.
- Follow existing naming conventions for columns, foreign keys, and indexes.
- Do not mix unrelated schema changes in a single migration.
- Be careful with destructive changes on existing production tables.
Blade and view rules
- Keep views dumb — presentation only.
- Avoid embedding business logic in Blade templates.
- Extract reusable UI pieces into components/partials when it matches project patterns.
- Escape output by default and use raw output only when safe and intentional.
Translations and language files
- Flat dot-notation keys only —
'type.daily_report' => 'Daily Report'.
Nested arrays ('type' => ['daily_report' => …]) are forbidden: they break
key referencing and make a one-line addition a nested diff.
- Reference with the helper and the same flat key —
__('report.type.daily_report'), __('email.report.created.subject', ['number' => $number]).
- Every key exists in every shipped locale. Adding to
lang/en/ without
lang/de/ is a bug, not a TODO — the app ships to both audiences.
- Never hardcode a user-visible string in PHP.
What NOT to do
- Do not put business logic into controllers, models, or Blade templates.
- Do not validate large requests inline in controllers when Form Requests are more appropriate.
- Do not call
env() outside config files.
- Do not introduce new architectural layers unless the project already uses them.
- Do not bypass Laravel features already used consistently in the project.
- Do not return inconsistent API response shapes in an established API.
Output expectations
When generating Laravel code:
- follow Laravel naming conventions
- use dependency injection
- keep classes small and focused
- match the surrounding project structure
- prefer explicit, readable code over clever abstractions
- integrate with existing requests, resources, services, policies, and tests
Output format
- Laravel code following framework conventions and project architecture
- All related files (controller, service, request, resource, test) as needed
Do NOT
- Do NOT put business logic in controllers — delegate to services.
- Do NOT use facades in service classes — use dependency injection.
- Do NOT skip middleware for route groups that need authentication.
Known pitfalls
| Symptom |
Root cause |
Fix |
| A list endpoint fires hundreds of queries / is slow under load |
N+1: a relation is accessed inside a loop without eager loading |
Eager-load with with('relation'); enable Model::preventLazyLoading() in non-prod to catch it early |
| Config changes / new env vars have no effect in production |
config:cache cached the old config, and env() returns null once config is cached |
Read env only in config/*, use config() elsewhere; re-run config:cache on deploy |
| A form field silently isn't saved |
The attribute isn't in $fillable and mass-assignment drops it |
Add it to $fillable (or set it explicitly); never blanket-$guarded = [] on user input |
| Queued jobs never run / run with stale code |
No worker is running, or workers weren't restarted after a deploy so they hold the old code in memory |
Run/supervise queue:work; queue:restart on every deploy |
| Timestamps or times are off by hours |
Comparing/formatting a Carbon instance without honoring config('app.timezone') vs the DB's UTC storage |
Store UTC; convert for display; set the app timezone explicitly, don't assume server local time |
Gotcha
env() only works in config files — use config() everywhere else.
- Don't mix
Route::resource() with single-action controllers — pick the project's convention.
- Don't return Eloquent models directly — always use API Resources.
- Don't bypass existing middleware stacks when adding new routes.
Auto-trigger keywords
- Laravel
- controller
- service
- middleware
- route
- application structure
Security audit checks (from security-audit)
Laravel-specific audit list (carved out of the generic security-audit
skill, 2026-07-12):
env() in non-config files (leaks in debug mode)
- Debug mode (
APP_DEBUG=true) in production
- Missing
$fillable on models used with request()->all()
Route::any() exposing unintended HTTP methods
- Missing rate limiting on login/register/password-reset
- Broadcast channels without proper authorization
- Missing encryption on sensitive cookie/session data
1---2name: laravel3description: Writes Laravel PHP — Eloquent, Artisan controllers, FormRequests, jobs, events, policies, providers. For Symfony / Doctrine use `symfony-workflow`. For framework-free PHP use `php-coder`.4---56# laravel78## When to use910Use this skill for all Laravel-specific code generation and editing tasks, especially when working with:1112- Controllers13- Form Requests14- Middleware15- Service Providers16- Jobs / Queued Jobs17- Events / Listeners18- Policies / Gates19- Notifications20- Console Commands21- Config, Routing, and Application Structure2223This skill extends the base `php-coder` skill and applies Laravel conventions on top of the project's general PHP rules.2425## When NOT to use — components without the framework2627```28A DEPENDENCY PROVES A LIBRARY IS AVAILABLE. ONLY THE ENTRY POINT AND THE29ROUTER PROVE WHICH APPLICATION SHAPE IS RUNNING.30`illuminate/*` PACKAGES WITH NO SKELETON MARKER IS A THIRD STATE, AND THIS SKILL31DOES NOT APPLY TO IT.32```3334Laravel ships its ORM, container, collections and HTTP layer as35independently installable packages, usable with no framework present — a36published distribution model, not one consumer's arrangement. An application37built that way has a **custom entry point and a custom router**. Routing it here38offers a CLI that does not exist, a request-validation primitive that is not39wired, and a routes file that was never there: every suggestion confidently40wrong, and the reason visible only from the entry point.4142**The probe set, and its cost.** A fixed set of filesystem existence checks plus43one manifest read — no directory walk, no content scan, and never re-derived per44session. Any ONE marker present means the framework is real:4546| Probe | Meaning |47|---|---|48| `artisan` | the console entry point the skeleton writes |49| `config/app.php` | the skeleton's bootstrap config |50| `bootstrap/app.php` | the application bootstrap |5152`illuminate/*` in `composer.json` with **none** of those markers is53*components-without-the-framework*. Say so and route away from this skill rather54than answering as though the framework were there.5556Implemented deterministically in `src/install/detect_php_shape.ts`57(`detectPhpShape`), whose `PROBE_PATHS` is this table and whose verdict names58what a wrong route would have offered.5960## Procedure: Write Laravel code6162→ **First apply the `php-coder` skill** — it handles project docs, module docs, patterns, and quality tools.6364Then add these **Laravel-specific** checks:65661. **Confirm this is a Laravel app** — check whether `artisan` exists.672. **Inspect app structure** — classic Laravel, modules (`app/Modules/`), or domain folders.683. **Check routes and HTTP flow** — understand how requests enter the application and where logic belongs.694. **Check test conventions** — inspect existing tests in the same domain before writing new code.7071## Core Laravel principles7273- Follow **Laravel conventions first** unless the project explicitly does otherwise.74- Keep **controllers thin** — delegate business logic to services/actions.75- Keep **Form Requests responsible for validation and authorization**.76- Use **dependency injection** through the container.77- Prefer **framework features** over custom infrastructure when the built-in solution is sufficient.78- Avoid hidden magic when explicit code is clearer for the project.79- Respect the existing architecture — do not force "pure Laravel" if the project uses modules or service layers.8081## HTTP layer rules8283- Controllers should:84 - accept the request85 - delegate business logic86 - return a response / resource / redirect87- Do not put business logic, calculations, or large data transformations in controllers.88- Use **Form Request** classes for validation instead of inline controller validation when the request is non-trivial.89- Use route model binding when it improves clarity and matches existing patterns.90- Keep controller actions focused and small.9192## Validation rules9394- Use **Form Requests** for reusable or non-trivial validation.95- Prefer explicit validation rules over implicit behavior.96- Reuse existing custom rules when available.97- Keep validation close to the HTTP boundary.98- Do not mix validation with persistence or business decisions.99100## Service layer rules101102- Put orchestration and business logic into dedicated services/actions.103- Services should be framework-light when possible.104- A service should have one clear responsibility.105- Prefer constructor injection for dependencies.106- Do not move trivial one-line controller behavior into a service unless the project consistently does that.107108## Routing rules109110- Follow the existing route organization:111 - `routes/web.php`112 - `routes/api.php`113 - module-specific route files114- Keep route definitions readable and grouped logically.115- Use route names consistently.116- Apply middleware explicitly and according to project conventions.117- Do not introduce route patterns that differ from the surrounding code without a good reason.118119## Response rules120121- Use the response style already established in the project:122 - Blade views123 - JSON responses124 - API Resources125 - Redirects with flash messages126- For APIs, prefer:127 - consistent status codes128 - structured JSON payloads129 - API Resources when the project uses them130- Do not return raw models directly unless that is already the established project pattern.131132## Queues, jobs, and async work133134- Use Jobs for clearly asynchronous or deferred work.135- Keep Jobs focused on a single responsibility.136- Pass only the data needed by the job.137- Avoid putting excessive domain logic directly into the Job class — delegate to services where appropriate.138- Be mindful of serialization when passing models or objects.139140## Events and listeners141142- Use events for meaningful domain or application events, not for every small action.143- Name events clearly in the past tense when something already happened.144- Keep listeners focused and side-effect oriented.145- Do not introduce event-driven complexity unless it is already part of the project architecture.146147## Auth, policies, and authorization148149- Use Laravel authorization features consistently:150 - policies151 - gates152 - request authorization153- Keep authorization logic out of controllers where possible.154- Reuse existing policies and permission patterns.155- Do not hardcode role checks in multiple places if a policy/gate already exists.156157## Config and environment158159- Read configuration from config files, not directly from `env()` outside config files.160- Do not introduce new environment variables unless necessary.161- Reuse existing config structure and naming patterns.162163## Database interaction164165- Prefer Eloquent for normal application data access unless the project uses repositories or query objects.166- Use transactions when multiple writes must succeed or fail together.167- Avoid N+1 problems — eager load when appropriate.168- For heavy data access logic, follow the dedicated `eloquent` skill.169170## Migrations and schema changes171172- Keep migrations focused and reversible.173- Follow existing naming conventions for columns, foreign keys, and indexes.174- Do not mix unrelated schema changes in a single migration.175- Be careful with destructive changes on existing production tables.176177## Blade and view rules178179- Keep views dumb — presentation only.180- Avoid embedding business logic in Blade templates.181- Extract reusable UI pieces into components/partials when it matches project patterns.182- Escape output by default and use raw output only when safe and intentional.183184## Translations and language files185186- **Flat dot-notation keys only** — `'type.daily_report' => 'Daily Report'`.187 Nested arrays (`'type' => ['daily_report' => …]`) are forbidden: they break188 key referencing and make a one-line addition a nested diff.189- Reference with the helper and the same flat key —190 `__('report.type.daily_report')`, `__('email.report.created.subject', ['number' => $number])`.191- Every key exists in **every** shipped locale. Adding to `lang/en/` without192 `lang/de/` is a bug, not a TODO — the app ships to both audiences.193- Never hardcode a user-visible string in PHP.194195## What NOT to do196197- Do not put business logic into controllers, models, or Blade templates.198- Do not validate large requests inline in controllers when Form Requests are more appropriate.199- Do not call `env()` outside config files.200- Do not introduce new architectural layers unless the project already uses them.201- Do not bypass Laravel features already used consistently in the project.202- Do not return inconsistent API response shapes in an established API.203204## Output expectations205206When generating Laravel code:207208- follow Laravel naming conventions209- use dependency injection210- keep classes small and focused211- match the surrounding project structure212- prefer explicit, readable code over clever abstractions213- integrate with existing requests, resources, services, policies, and tests214215## Output format2162171. Laravel code following framework conventions and project architecture2182. All related files (controller, service, request, resource, test) as needed219220## Do NOT221222- Do NOT put business logic in controllers — delegate to services.223- Do NOT use facades in service classes — use dependency injection.224- Do NOT skip middleware for route groups that need authentication.225226## Known pitfalls227228| Symptom | Root cause | Fix |229|---|---|---|230| A list endpoint fires hundreds of queries / is slow under load | N+1: a relation is accessed inside a loop without eager loading | Eager-load with `with('relation')`; enable `Model::preventLazyLoading()` in non-prod to catch it early |231| Config changes / new env vars have no effect in production | `config:cache` cached the old config, and `env()` returns `null` once config is cached | Read env only in `config/*`, use `config()` elsewhere; re-run `config:cache` on deploy |232| A form field silently isn't saved | The attribute isn't in `$fillable` and mass-assignment drops it | Add it to `$fillable` (or set it explicitly); never blanket-`$guarded = []` on user input |233| Queued jobs never run / run with stale code | No worker is running, or workers weren't restarted after a deploy so they hold the old code in memory | Run/supervise `queue:work`; `queue:restart` on every deploy |234| Timestamps or times are off by hours | Comparing/formatting a Carbon instance without honoring `config('app.timezone')` vs the DB's UTC storage | Store UTC; convert for display; set the app timezone explicitly, don't assume server local time |235236## Gotcha237238- `env()` only works in config files — use `config()` everywhere else.239- Don't mix `Route::resource()` with single-action controllers — pick the project's convention.240- Don't return Eloquent models directly — always use API Resources.241- Don't bypass existing middleware stacks when adding new routes.242243## Auto-trigger keywords244245- Laravel246- controller247- service248- middleware249- route250- application structure251252## Security audit checks (from security-audit)253254Laravel-specific audit list (carved out of the generic `security-audit`255skill, 2026-07-12):256257- `env()` in non-config files (leaks in debug mode)258- Debug mode (`APP_DEBUG=true`) in production259- Missing `$fillable` on models used with `request()->all()`260- `Route::any()` exposing unintended HTTP methods261- Missing rate limiting on login/register/password-reset262- Broadcast channels without proper authorization263- Missing encryption on sensitive cookie/session data