本文へスキップ
Pathrule

パターン

このページは英語でのみご覧いただけます。

Laravel

Pathruleルール3件 • メモリ2件 • スキル1件

A bundle for teams on Laravel 12 and 13 that keeps agents on the framework's own idioms instead of generic PHP. It covers the four places Laravel apps rot: Eloquent relations that lazy-load inside a Blade loop, controllers that read straight from the request, jobs that are not idempotent and duplicate work on retry, and a production deploy that never caches config or routes. Written so each piece lands on the directory it governs rather than in one README nobody scopes.

推奨されるパスの配置

Pathruleは各要素を対応するパスに配置するため、アシスタントはそれが属する場所でだけ参照します。これはインポート時に適用されるスコープで、ワークスペースで調整できます。

/ ワークスペースのルート
laravel-pre-merge-review
app/
Eager-load every relation a view or resource reads
Where code goes in a Laravel app, and what stays out of the container
Http/
Validate in a form request and authorize with a policy
Jobs/
Make queued jobs idempotent and bounded
database/
Migrations, seeders, and the production deploy sequence

ルール

3
Eager-load every relation a view or resource reads/app高強制Declare `with()` on the query that feeds a view, resource, or export, and fail loudly on lazy loading in local and CI.
1Eloquent will happily run one query per row, and Blade makes it invisible: the loop reads `$order->customer->name` and the page fires 200 queries.
2 
3- Load relations on the query, not in the template: `Order::with(['customer', 'items.product'])`. If a Blade view, API resource, or export touches a relation, the query that feeds it declares it.
4- Turn lazy loading into an error outside production with `Model::preventLazyLoading(! app()->isProduction())` in a service provider. This is the single highest-value line in a Laravel app.
5- Use `withCount` for counts, `chunk`/`lazy`/`cursor` for large sets, and `select` the columns you need. Loading full models to count them is wasted memory.
6- Never call a query inside an accessor or a `map` over a collection. Load what you need in one query and key it by id.
7- Watch the inverse too: `whereHas` on a deep relation can be slower than a join with an index. Read the query log before optimising by feel.
Validate in a form request and authorize with a policy/app/Http高強制Every write endpoint takes a typed FormRequest and checks a policy or gate; controllers never read unvalidated input or trust a route id.
1Laravel gives you validation and authorization as first-class layers. Skipping them is what turns a mass-assignment convenience into a privilege escalation.
2 
3- Put validation in a `FormRequest` per endpoint. The controller receives validated data, never `$request->all()`. Rules live with the endpoint, not scattered across the action.
4- Authorize with a policy or gate for every action on a model, and check ownership of the specific record. A route model binding proves the record exists, not that this user may touch it.
5- Keep `$fillable` (or `$guarded`) accurate on every model and pass only validated data to `create`/`update`. `Model::unguard()` in application code is a bug.
6- Return an API resource rather than the model, so a new database column never leaks into a public response by accident.
7- Rate-limit authentication and other abuse-prone routes with the framework's throttle middleware.
8 
9See the web-security pattern for the app-level authorization and input rules this mirrors.
Make queued jobs idempotent and bounded/app/Jobs高強制Queues deliver at least once: give every job a retry budget, a unique lock where it must not overlap, and a side effect that is safe to repeat.
1A queued job will run twice eventually: a worker is killed mid-run, a deploy restarts the pool, a transient failure triggers a retry. Design for the second run.
2 
3- Set `$tries` and `$backoff` (or `retryUntil`) on every job. A job with unlimited retries and a permanent failure is an infinite loop that burns the queue.
4- Make the side effect idempotent: check state before acting, or key it on something stable so a repeat is a no-op. Charging a card, sending an email, or incrementing a counter twice must be impossible.
5- Use `ShouldBeUnique` (or an explicit cache lock) for jobs that must not overlap for the same subject, and `ShouldBeUniqueUntilProcessing` where only the queued window matters.
6- Dispatch after the transaction commits (`dispatch()->afterCommit()` or `after_commit` on the connection). A job that reads a row the transaction has not committed yet fails intermittently and is a nightmare to reproduce.
7- Pass ids, not serialized models, and handle the row being gone. Implement `failed()` so a dead job leaves a trace instead of silence.
8 
9See the background-jobs-queues pattern for the queue-agnostic version of these constraints.

メモリ

2
Where code goes in a Laravel app, and what stays out of the container/appActions and services hold workflows, models hold scopes and casts, and anything expensive is resolved lazily rather than in a provider boot.
1Laravel's structure is loose enough that two developers produce two architectures. Pick the conventional one and stay in it.
2 
3- Controllers stay thin: resolve, delegate, respond. Multi-step workflows go in a single-purpose action or service class under `App\Actions` or `App\Services`, which is testable without HTTP and reusable from a command or job.
4- Models own their query vocabulary: local scopes for reusable filters, casts for value conversion, accessors for derived display values. Business decisions that span models do not belong there.
5- Avoid heavy work in a service provider's `boot()`. It runs on every request, including artisan commands and health checks. Bind lazily and let the container resolve on demand.
6- Prefer explicit event listeners over model events for anything a reader needs to know about, and never rely on model events in bulk paths: `Model::query()->update()` bypasses them entirely, exactly like Eloquent's docs say.
7- Keep Blade for presentation. A view that queries, formats money, or decides permissions is a view that cannot be tested.
8 
9See /app/Http for the request rules and /app/Jobs for the queue rules.
Migrations, seeders, and the production deploy sequence/databaseMigrations are forward-only in production, seeders stay idempotent, and every deploy caches config, routes, views, and events.
1Most Laravel production surprises come from the deploy, not the code.
2 
3- Cache everything the framework can precompute on deploy: `config:cache`, `route:cache`, `view:cache`, `event:cache`. Without config caching, every request re-reads your config tree, and `env()` calls outside config files return null once caching is on. Read config, never `env()`, at runtime.
4- Run `migrate --force` as part of the release, and treat migrations as forward-only in production. Rolling back a shipped migration is a data decision, not a command.
5- Keep destructive schema changes multi-step: add nullable, deploy writers, backfill, then constrain or drop. On MySQL, an added index or a changed column type can lock a large table.
6- Seeders are for reference data and must be idempotent (`upsert`/`firstOrCreate`), so re-running one does not duplicate rows. Test data belongs in factories.
7- Restart the queue workers after every deploy (`queue:restart`); long-lived workers keep the old code in memory until they cycle.
8 
9See /app/Jobs for the job design that makes a worker restart safe.

スキル

1
laravel-pre-merge-review/rootChecklist for any Laravel change that adds a controller, model query, job, or migration.
1---
2name: laravel-pre-merge-review
3description: Laravel review checklist covering Eloquent query efficiency, request validation and authorization, queued job safety, and deploy-time caching. Run before merging.
4---
5 
6# Laravel review
7 
8## Eloquent
9- [ ] Every relation the view, resource, or export reads is eager-loaded on the query.
10- [ ] No query inside a loop, accessor, or collection callback.
11- [ ] `preventLazyLoading` is on outside production and the change does not trip it.
12- [ ] Large reads use `chunk`, `lazy`, or `cursor`; counts use `withCount`.
13 
14## Request handling
15- [ ] Writes take a `FormRequest`; the controller never reads `$request->all()`.
16- [ ] A policy or gate authorizes the action on the specific record.
17- [ ] Responses go through an API resource; `$fillable` is accurate.
18 
19## Jobs and events
20- [ ] `$tries` and `$backoff` are set; the side effect is safe to repeat.
21- [ ] Overlap-sensitive jobs use `ShouldBeUnique` or an explicit lock.
22- [ ] Dispatch happens after commit; the job takes ids, not models, and handles a missing row.
23 
24## Migrations and deploy
25- [ ] Schema change is additive, or split into add, backfill, constrain.
26- [ ] No runtime `env()` call outside a config file.
27- [ ] Seeder changes are idempotent.

このパターンを使う理由

AI agents write Laravel code that lazy-loads relations inside Blade loops, validates inline in controllers, authorizes nowhere, and queues jobs that duplicate work when they retry.

対象:PHP teams shipping Laravel 12 or 13 applications

アシスタントが次のことをしないようにします。

  • Lazy-loading a relation inside a Blade or collection loop and firing N queries
  • Reading request input directly in a controller with no validation or authorization
  • Queueing a job that repeats its side effect every time the queue retries it
  • Deploying without caching config, routes, views, and events
ライセンス
Apache-2.0
バージョン
1.0.0
更新日
2026-08-24
ソースを見る