PHP Idioms and Patterns
Modern PHP (8.x) rewards type safety, immutability, and framework-agnostic design. Lean into typed properties, enums, and readonly classes. Idiomatic PHP = strict types, PSR-compliant, well-tested.
Scope: PHP coding idioms. Test naming: GEMINI.md § Testing Strategy. Logging:
@.gemini/skills/logging-and-observability-principles/SKILL.md.
Modern PHP Features (8.x)
declare(strict_types=1)— always, every file.Enums for domain constants:
enum Priority: string { case Low = 'low'; case Medium = 'medium'; case High = 'high'; }Readonly classes for immutable DTOs:
readonly class CreateTaskRequest { public function __construct( public string $title, public Priority $priority, ) {} }Named arguments for clarity:
$task = new Task(title: 'Deploy fix', priority: Priority::High);Match expressions over switch:
$score = match($priority) { Priority::Low => 1, Priority::Medium => 5, Priority::High => 10, };
Error Handling
Domain exception hierarchies:
abstract class DomainException extends \RuntimeException {} class NotFoundException extends DomainException { public function __construct( public readonly string $resource, public readonly string $resourceId, ) { parent::__construct("{$resource} '{$resourceId}' not found"); } }Never
catch (\Exception)without re-throw or specific handling.Type-safe return types — never mixed without justification.
Interfaces and DI
- Define interface where consumed, implement where provided:
// In task feature interface TaskStorage { public function getById(string $id): Task; public function save(Task $task): void; } // Constructor injection class TaskService { public function __construct( private readonly TaskStorage $storage, ) {} }
Naming (PSR-12)
- PascalCase for classes, interfaces, traits, enums.
- camelCase for methods, properties.
- UPPER_SNAKE_CASE for constants.
- PSR-4 autoloading — namespace = directory path.
Testing
PHPUnit or Pest:
test('calculate discount returns zero for no items', function () { $result = $this->calculator->calculateDiscount([], $this->coupon); expect($result)->toBe(0.0); });Data providers for parameterized tests.
Mockery or PHPUnit mocks — never test implementation details.
Formatting and Static Analysis
| Tool | Purpose | Command |
|---|---|---|
| PHP CS Fixer | PSR-12 formatting | php-cs-fixer fix . |
| PHPStan (level 9) | Static analysis | phpstan analyse src/ --level 9 |
| Psalm | Type checking | psalm --show-info=true |
composer audit |
CVE scanning | composer audit |
Related
- Code Idioms and Conventions GEMINI.md § Code Idioms and Conventions
- Testing Strategy GEMINI.md § Testing Strategy
- Error Handling Principles GEMINI.md § Error Handling Principles