# PHP Skill ## Purpose Use this skill for PHP language rules, coding style, Composer, namespacing, autoloading, object-oriented design, dependency injection, documentation, and performance. Source reference: ```text https://phptherightway.com/ ``` --- ## Core Philosophy Write PHP that is: - Readable before clever. - Secure by default. - Consistent with community standards. - Easy to test, debug, and refactor. - Separated by responsibility. PHP does not have only one canonical “right way,” so prefer widely accepted standards, documented project conventions, and clear tradeoffs over personal style. --- ## PHP Version Standard Use the current stable PHP version supported by the project. Default expectation: ```text PHP 8.2+ ``` Do not introduce code that depends on unsupported PHP versions unless the project explicitly targets a legacy runtime. When adding a language feature, verify that it is supported by the project’s configured PHP version in `composer.json`. Example: ```json { "require": { "php": ">=8.2" } } ``` --- ## Coding Style Follow recognized PHP standards unless the repository already defines stricter rules. Preferred standards: - PSR-1: Basic Coding Standard - PSR-12: Extended Coding Style - PSR-4: Autoloading Use automated tooling rather than manual formatting arguments. Recommended tools: ```bash composer require --dev squizlabs/php_codesniffer composer require --dev friendsofphp/php-cs-fixer ``` Example checks: ```bash vendor/bin/phpcs --standard=PSR12 src tests vendor/bin/php-cs-fixer fix --dry-run --diff ``` Example fix: ```bash vendor/bin/php-cs-fixer fix ``` --- ## Naming Rules Use English names for code symbols and infrastructure. Good: ```php class InvoiceRepository { public function findByCustomerId(int $customerId): array { // ... } } ``` Avoid unclear abbreviations: ```php class InvRepo { public function fbcid($cid) { // ... } } ``` --- ## Formatting Rules - Use `value; } } ``` Guidelines: - Keep controllers thin. - Put business rules in services or domain objects. - Put persistence logic in repositories or data access classes. - Use interfaces when multiple implementations are expected or when it improves testing. - Avoid huge “utility” classes. - Avoid magic methods unless they provide clear framework integration or a documented benefit. --- ## Dependency Injection Prefer dependency injection over creating dependencies inside classes. Good: ```php final class RegisterUser { public function __construct( private UserRepository $users, private PasswordHasher $passwords ) { } public function handle(string $email, string $plainPassword): void { $hash = $this->passwords->hash($plainPassword); $this->users->create($email, $hash); } } ``` Avoid: ```php final class RegisterUser { public function handle(string $email, string $plainPassword): void { $users = new UserRepository(); $passwords = new PasswordHasher(); } } ``` Rules: - Constructor injection is preferred for required dependencies. - Do not use service locators casually. - Do not hide dependencies in global variables. - Keep dependency containers at application boundaries, not inside domain logic. --- ## Documentation Rules Use PHPDoc where it adds clarity, especially for arrays, complex return values, and public APIs. Good: ```php /** * @return list */ public function findActiveCustomers(): array { // ... } ``` Avoid noisy comments that repeat the code: ```php // Increment i by one. $i++; ``` Rules: - Explain why, not just what. - Document non-obvious tradeoffs. - Keep README setup instructions current. - Update examples when behavior changes. --- ## Performance and Caching Rules: - Measure before optimizing. - Avoid unnecessary database queries in loops. - Use pagination for large result sets. - Cache expensive reads where appropriate. - Use OPcache in production. - Do not cache user-specific sensitive data in shared caches without a clear key strategy.