The interface is localized. Skill descriptions and documents are machine-translated by AI into your language; code, commands, paths and technical terms stay in the original, and the author's document governs.
Explore skills
Development · SKILL.md

php-laravel

php-laravel

Modern 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.

Independent GitHub snapshot · Automated classification · Original documentation governs

Skill documentation

GitHub

name: php-laravel description: >- Modern 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.

PHP & Laravel Development

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 — $exception not $e, $request not $r
  • ?string not string|null. Always specify void. 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)|null for 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 responses
  • when() / mergeWhen() for permission-based field inclusion
  • whenPivotLoaded() for pivot data
  • withResponse() 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() => ...)
  • ShouldBeUnique interface to prevent duplicate processing
  • Always handle failures — implement failed() method on jobs

Testing (Pest)

  • RED → verify RED → GREEN → verify GREEN → REFACTOR
  • test() / it() syntax with RefreshDatabase trait
  • 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 $fillable instead
  • Inline validation in controllers — use Form Requests instead
Saved skills