Use when writing PHP 8.2+ or working in Laravel and Symfony codebases. Covers strict types, enums, readonly classes, attributes, PSR standards, and static analysis with PHPStan.
Scanned 9/6/2026
Install to Claude Code
npx -y skills add nimadorostkar/Claude-Skills-collection --skill php --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Php?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/nimadorostkar-php)More formats (shields.io, HTML) on the badges page.
---
name: php
description: Use when writing PHP 8.2+ or working in Laravel and Symfony codebases. Covers strict types, enums, readonly classes, attributes, PSR standards, and static analysis with PHPStan.
metadata:
category: languages
version: 1.0.0
tags: [php, laravel, symfony, phpstan, psr]
---
# PHP
## Purpose
Write PHP that behaves like a typed language: strict types on, enums instead of string constants, readonly value objects, and PHPStan at a level high enough to catch real defects.
## When to Use
- Writing or reviewing PHP 8.2+.
- Working in Laravel or Symfony applications.
- Introducing static analysis to a legacy PHP codebase.
- Modeling domain values and states.
- Fixing performance problems in ORM-heavy code.
## Capabilities
- Strict typing, union and intersection types, `never` and `readonly`.
- Enums with backing values and interfaces.
- Attributes for routing, validation, and DI metadata.
- PSR-4 autoloading, PSR-12 style, PSR-3 logging.
- PHPStan configuration and incremental adoption via baselines.
## Inputs
- Source tree, `composer.json`, framework and version.
- Existing analysis configuration and baseline, if any.
## Outputs
- Files opening with `declare(strict_types=1);`.
- Typed properties, parameters, and return types throughout.
- A PHPStan configuration at level 8 (or a baseline plus a plan to reach it).
## Workflow
1. **Turn on strictness** — `declare(strict_types=1)` in every file; PHPStan with a baseline to freeze existing debt.
2. **Replace magic with types** — String constants become enums; array shapes become value objects or DTOs.
3. **Implement** — Constructor promotion, readonly properties, named arguments at call sites.
4. **Eliminate ORM traps** — Eager-load relations; never query inside a loop.
5. **Gate** — PHPStan, PHP-CS-Fixer, PHPUnit or Pest.
## Best Practices
- Never use `array` as a domain type. An untyped array is a shape that no tool can check.
- Enums replace class constants and give you exhaustive `match`.
- Readonly promoted constructor properties are the shortest path to immutable value objects.
- In Eloquent, `with()` your relations. An N+1 query in a list endpoint is the single most common PHP performance defect.
- Do not catch `\Exception` broadly. Catch the specific type, or let it reach the handler.
- Keep framework types out of the domain layer — a domain service should not know what an HTTP request is.
## Examples
**Enum plus readonly value object:**
```php
<?php
declare(strict_types=1);
enum SubscriptionState: string
{
case Trialing = 'trialing';
case Active = 'active';
case PastDue = 'past_due';
case Cancelled = 'cancelled';
public function isBillable(): bool
{
return match ($this) {
self::Active, self::PastDue => true,
self::Trialing, self::Cancelled => false,
};
}
}
final readonly class Subscription
{
public function __construct(
public string $id,
public SubscriptionState $state,
public \DateTimeImmutable $renewsAt,
) {}
}
```
## Notes
- PHPStan level 8 adds null-safety checks; it is the level where the tool starts finding real bugs rather than style issues.
- `readonly` classes (8.2) make every property readonly implicitly — a cleaner default for DTOs.
- Laravel's `lazy()` and `chunk()` prevent memory exhaustion on large result sets; `get()` on an unbounded query will eventually take the process down.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!