php-best-practices
SKILL.md
PHP Best Practices
Modern PHP 8.x patterns, PSR standards, type system best practices, and SOLID principles. Contains 45+ rules for writing clean, maintainable PHP code.
When to Apply
Reference these guidelines when:
- Writing or reviewing PHP code
- Implementing classes and interfaces
- Using PHP 8.x modern features
- Ensuring type safety
- Following PSR standards
- Applying design patterns
Rule Categories by Priority
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Type System | CRITICAL | type- |
| 2 | Modern Features | CRITICAL | modern- |
| 3 | PSR Standards | HIGH | psr- |
| 4 | SOLID Principles | HIGH | solid- |
| 5 | Error Handling | HIGH | error- |
| 6 | Performance | MEDIUM | perf- |
| 7 | Security | CRITICAL | sec- |
Quick Reference
1. Type System (CRITICAL)
type-strict-mode- Declare strict typestype-return-types- Always declare return typestype-parameter-types- Type all parameterstype-property-types- Type class propertiestype-union-types- Use union types effectivelytype-intersection-types- Use intersection typestype-nullable- Handle nullable types properlytype-mixed-avoid- Avoid mixed type when possibletype-void-return- Use void for no-return methodstype-never-return- Use never for non-returning functions
2. Modern Features (CRITICAL)
modern-constructor-promotion- Use constructor property promotionmodern-readonly-properties- Use readonly for immutable datamodern-readonly-classes- Use readonly classesmodern-enums- Use enums instead of constantsmodern-attributes- Use attributes for metadatamodern-match-expression- Use match over switchmodern-named-arguments- Use named arguments for claritymodern-nullsafe-operator- Use nullsafe operator (?->)modern-arrow-functions- Use arrow functions for simple closuresmodern-first-class-callables- Use first-class callable syntax
3. PSR Standards (HIGH)
psr-4-autoloading- Follow PSR-4 autoloadingpsr-12-coding-style- Follow PSR-12 coding stylepsr-naming-conventions- Class and method namingpsr-file-structure- One class per filepsr-namespace-declaration- Proper namespace usage
4. SOLID Principles (HIGH)
solid-single-responsibility- One reason to changesolid-open-closed- Open for extension, closed for modificationsolid-liskov-substitution- Subtypes must be substitutablesolid-interface-segregation- Small, focused interfacessolid-dependency-inversion- Depend on abstractions
5. Error Handling (HIGH)
error-custom-exceptions- Create specific exceptionserror-exception-hierarchy- Proper exception inheritanceerror-try-catch-specific- Catch specific exceptionserror-finally-cleanup- Use finally for cleanuperror-never-suppress- Don't suppress errors with @
6. Performance (MEDIUM)
perf-avoid-globals- Avoid global variablesperf-lazy-loading- Load resources lazilyperf-array-functions- Use native array functionsperf-string-functions- Use native string functionsperf-generators- Use generators for large datasets
7. Security (CRITICAL)
sec-input-validation- Validate all inputsec-output-escaping- Escape output properlysec-password-hashing- Use password_hash/verifysec-sql-prepared- Use prepared statementssec-file-uploads- Validate file uploads
Essential Guidelines
For detailed examples and explanations, see the rule files:
- type-strict-mode.md - Strict types declaration
- modern-constructor-promotion.md - Constructor property promotion
- modern-enums.md - PHP 8.1+ enums with methods
- solid-single-responsibility.md - Single responsibility principle
Key Patterns (Quick Reference)
<?php
declare(strict_types=1);
// Constructor promotion + readonly
class User
{
public function __construct(
public readonly string $id,
private string $email,
) {}
}
// Enums with methods
enum Status: string
{
case Active = 'active';
case Inactive = 'inactive';
public function label(): string
{
return match($this) {
self::Active => 'Active',
self::Inactive => 'Inactive',
};
}
}
// Match expression
$result = match($status) {
'pending' => 'Waiting',
'active' => 'Running',
default => 'Unknown',
};
// Nullsafe operator
$country = $user?->getAddress()?->getCountry();
// Arrow functions
$names = array_map(fn(User $u) => $u->name, $users);
Output Format
When auditing code, output findings in this format:
file:line - [category] Description of issue
Example:
src/Services/UserService.php:15 - [type] Missing return type declaration
src/Models/Order.php:42 - [modern] Use match expression instead of switch
src/Controllers/ApiController.php:28 - [solid] Class has multiple responsibilities
How to Use
Read individual rule files for detailed explanations:
rules/modern-constructor-promotion.md
rules/type-strict-mode.md
rules/solid-single-responsibility.md