Claude
Skill
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.
Virus-scanned
Reviewed automatically before listing.
Download
iliaal-whetstone-distillery_generated-skills_php-laravel-bccd699.zip · 2 KB
Install
skills CLI
npx skills add https://github.com/iliaal/whetstone/tree/master/distillery/generated-skills/php-laravel
Claude Code
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install iliaal-whetstone@llmmart
Git
git clone https://github.com/iliaal/whetstone.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole iliaal/whetstone collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
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 —
$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
Files (whetstone)
-
manifest.json 1.1 KB
{ "query": "php-laravel", "search_queries": [ "PHP", "Laravel" ], "generated": "2026-02-13", "token_count": 1039, "sources": [ { "id": "jeffallan/claude-skills/laravel-specialist", "installs": 1105, "sha1": "1b9e632c4f1bb5c7c03073845f899c8a58054d32" }, { "id": "jeffallan/claude-skills/php-pro", "installs": 640, "sha1": "4ed9bb0e784ba6799863a2e8493f60ac1e247073" }, { "id": "iserter/laravel-claude-agents/eloquent-best-practices", "installs": 230, "sha1": "2129093402e4e6ce04af1da7b805a0efa555a088" }, { "id": "thienanblog/awesome-ai-agent-skills/laravel-11-12-app-guidelines", "installs": 193, "sha1": "7e7520938b5326c6eeb98d59ca164db6f770c9c0" }, { "id": "asyrafhussin/agent-skills/php-best-practices", "installs": 193, "sha1": "f9ad3621d15dbd9c188b4df3459ecf3b421eb201" }, { "id": "asyrafhussin/agent-skills/laravel-best-practices", "installs": 119, "sha1": "2f11466d0263788d87a5a7e445525bc8dc56c5cb" } ] } -
SKILL.md 4.2 KB
--- 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
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.