php-idioms
SkillAI & modelsModern 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.
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-idioms skill
About this capability
Comprehensive sets of standards and practices designed to elevate the capabilities of AI coding agents.
What this skill tells your AI
The instructions your AI receives, as published by irahardianto/awesome-agv in .agents/skills/php-idioms/SKILL.md and read by ahel’s review.
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: .agents/rules/testing-strategy.md. Logging:
@.agents/skills/logging-implementation/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 .agents/rules/code-idioms-and-conventions.md
- Testing Strategy .agents/rules/testing-strategy.md
- Error Handling Principles .agents/rules/error-handling-principles.md
Signals
- GitHub stars
- 156
- Forks
- 53
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
php-idioms- Source
- github.com/irahardianto/awesome-agv