PHP & Laravel Development
SkillDev toolsModern PHP 8.2+ and Laravel patterns: architecture, Eloquent, queues, Pest testing. Use when asked to "write PHP", "build a Laravel app", "fix Eloquent query", "add a queue job", "write a Pest test", or mentions PHP, Laravel, Eloquent, Blade, artisan, or migrations.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the PHP & Laravel Development skill
What this skill tells your AI
The instructions your AI receives, as published by iliaal/whetstone in distillery/generated-skills/php-laravel/SKILL.md and read by ahel’s review.
Code Style
declare(strict_types=1)in every file- Happy path last — handle errors/guards first, success at the end. Use early returns; avoid
else. - Comments only explain why, never what. Never comment tests. If code needs a "what" comment, rename or restructure instead.
- No single-letter variables —
$exceptionnot$e,$requestnot$r ?stringnotstring|null. Always specifyvoid. Import classnames everywhere, never inline FQN.- Validation uses array notation
['required', 'email']for easier custom rule classes
Modern PHP (8.2+)
Use these when applicable — do not explain them in comments (Claude and developers know them):
- Readonly classes and properties for immutable data
- Enums with methods and interfaces for domain constants
- Match expressions over switch
- Constructor promotion with readonly
- First-class callable syntax
$fn = $obj->method(...) - Fibers for cooperative async when Swoole/ReactPHP not available
- DNF types
(Stringable&Countable)|nullfor complex constraints
Laravel Architecture
- Fat models, thin controllers — controllers only: validate, call service/action, return response
- Service classes for business logic with readonly DI:
__construct(private readonly PaymentService $payments) - Action classes (single-purpose invokable) for operations that cross service boundaries
- Form Requests for all validation — never validate inline in controllers
- Events + Listeners for side effects (notifications, logging, cache invalidation). Do not put side effects in services.
- Feature folder organization over type-based when project exceeds ~20 models
Eloquent
Model::preventLazyLoading(!app()->isProduction())— catch N+1 during development- Select only needed columns:
Post::with(['user:id,name'])->select(['id', 'title', 'user_id']) - Bulk operations at database level:
Post::where('status', 'draft')->update([...])— do not load into memory to update increment()/decrement()for counters in a single query- Composite indexes for common query combinations
- Chunking for large datasets (
chunk(1000)), lazy collections for memory-constrained processing $guarded = []is a mass assignment vulnerability — always use explicit$fillable
API Resources
whenLoaded()for relationships — prevents N+1 in responseswhen()/mergeWhen()for permission-based field inclusionwhenPivotLoaded()for pivot datawithResponse()for custom headers,with()for metadata (version, pagination)
Queues & Jobs
- Job batching with
Bus::batch([...])->then()->catch()->finally()->dispatch() - Job chaining for sequential ops:
Bus::chain([new Step1, new Step2])->dispatch() - Rate limiting:
Redis::throttle('api')->allow(10)->every(60)->then(fn() => ...) ShouldBeUniqueinterface to prevent duplicate processing- Always handle failures — implement
failed()method on jobs
Testing (Pest)
- RED → verify RED → GREEN → verify GREEN → REFACTOR
test()/it()syntax withRefreshDatabasetrait- One assertion focus per test. Test name describes the behavior, not the method.
Sanctum::actingAs($user, ['ability'])for API auth testing- Run relevant tests first, offer full suite after
Discipline
- For non-trivial changes, pause and ask: "is there a more elegant way?" Skip for obvious fixes.
- Simplicity first — every change as simple as possible, impact minimal code
- Only touch what's necessary — avoid introducing unrelated changes
- No hacky workarounds — if a fix feels wrong, step back and implement the clean solution
Anti-Patterns
- Querying in loops — use eager loading or
whereIn()instead - Empty catch blocks — log or rethrow, never swallow
- Business logic in controllers — extract to service/action instead
protected $guarded = []— use$fillableinstead- Inline validation in controllers — use Form Requests instead
Signals
- GitHub stars
- 33
- Forks
- 3
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
php-laravel-iliaal- Source
- github.com/iliaal/whetstone