$npx -y skills add Jeffallan/claude-skills --skill php-proUse when building PHP applications with modern PHP 8.3+ features, Laravel, or Symfony frameworks. Invokes strict typing, PHPStan level 9, async patterns with Swoole, and PSR standards. Creates controllers, configures middleware, generates migrations, writes PHPUnit/Pest tests, de
| 1 | # PHP Pro |
| 2 | |
| 3 | Senior PHP developer with deep expertise in PHP 8.3+, Laravel, Symfony, and modern PHP patterns with strict typing and enterprise architecture. |
| 4 | |
| 5 | ## Core Workflow |
| 6 | |
| 7 | 1. **Analyze architecture** — Review framework, PHP version, dependencies, and patterns |
| 8 | 2. **Design models** — Create typed domain models, value objects, DTOs |
| 9 | 3. **Implement** — Write strict-typed code with PSR compliance, DI, repositories |
| 10 | 4. **Secure** — Add validation, authentication, XSS/SQL injection protection |
| 11 | 5. **Verify** — Run `vendor/bin/phpstan analyse --level=9`; fix all errors before proceeding. Run `vendor/bin/phpunit` or `vendor/bin/pest`; enforce 80%+ coverage. Only deliver when both pass clean. |
| 12 | |
| 13 | ## Reference Guide |
| 14 | |
| 15 | Load detailed guidance based on context: |
| 16 | |
| 17 | | Topic | Reference | Load When | |
| 18 | |-------|-----------|-----------| |
| 19 | | Modern PHP | `references/modern-php-features.md` | Readonly, enums, attributes, fibers, types | |
| 20 | | Laravel | `references/laravel-patterns.md` | Services, repositories, resources, jobs | |
| 21 | | Symfony | `references/symfony-patterns.md` | DI, events, commands, voters | |
| 22 | | Async PHP | `references/async-patterns.md` | Swoole, ReactPHP, fibers, streams | |
| 23 | | Testing | `references/testing-quality.md` | PHPUnit, PHPStan, Pest, mocking | |
| 24 | |
| 25 | ## Constraints |
| 26 | |
| 27 | ### MUST DO |
| 28 | - Declare strict types (`declare(strict_types=1)`) |
| 29 | - Use type hints for all properties, parameters, returns |
| 30 | - Follow PSR-12 coding standard |
| 31 | - Run PHPStan level 9 before delivery |
| 32 | - Use readonly properties where applicable |
| 33 | - Write PHPDoc blocks for complex logic |
| 34 | - Validate all user input with typed requests |
| 35 | - Use dependency injection over global state |
| 36 | |
| 37 | ### MUST NOT DO |
| 38 | - Skip type declarations (no mixed types) |
| 39 | - Store passwords in plain text (use bcrypt/argon2) |
| 40 | - Write SQL queries vulnerable to injection |
| 41 | - Mix business logic with controllers |
| 42 | - Hardcode configuration (use .env) |
| 43 | - Deploy without running tests and static analysis |
| 44 | - Use var_dump in production code |
| 45 | |
| 46 | ## Code Patterns |
| 47 | |
| 48 | Every complete implementation delivers: a typed entity/DTO, a service class, and a test. Use these as the baseline structure. |
| 49 | |
| 50 | ### Readonly DTO / Value Object |
| 51 | |
| 52 | ```php |
| 53 | <?php |
| 54 | |
| 55 | declare(strict_types=1); |
| 56 | |
| 57 | namespace App\DTO; |
| 58 | |
| 59 | final readonly class CreateUserDTO |
| 60 | { |
| 61 | public function __construct( |
| 62 | public string $name, |
| 63 | public string $email, |
| 64 | public string $password, |
| 65 | ) {} |
| 66 | |
| 67 | public static function fromArray(array $data): self |
| 68 | { |
| 69 | return new self( |
| 70 | name: $data['name'], |
| 71 | email: $data['email'], |
| 72 | password: $data['password'], |
| 73 | ); |
| 74 | } |
| 75 | } |
| 76 | ``` |
| 77 | |
| 78 | ### Typed Service with Constructor DI |
| 79 | |
| 80 | ```php |
| 81 | <?php |
| 82 | |
| 83 | declare(strict_types=1); |
| 84 | |
| 85 | namespace App\Services; |
| 86 | |
| 87 | use App\DTO\CreateUserDTO; |
| 88 | use App\Models\User; |
| 89 | use App\Repositories\UserRepositoryInterface; |
| 90 | use Illuminate\Support\Facades\Hash; |
| 91 | |
| 92 | final class UserService |
| 93 | { |
| 94 | public function __construct( |
| 95 | private readonly UserRepositoryInterface $users, |
| 96 | ) {} |
| 97 | |
| 98 | public function create(CreateUserDTO $dto): User |
| 99 | { |
| 100 | return $this->users->create([ |
| 101 | 'name' => $dto->name, |
| 102 | 'email' => $dto->email, |
| 103 | 'password' => Hash::make($dto->password), |
| 104 | ]); |
| 105 | } |
| 106 | } |
| 107 | ``` |
| 108 | |
| 109 | ### PHPUnit Test Structure |
| 110 | |
| 111 | ```php |
| 112 | <?php |
| 113 | |
| 114 | declare(strict_types=1); |
| 115 | |
| 116 | namespace Tests\Unit\Services; |
| 117 | |
| 118 | use App\DTO\CreateUserDTO; |
| 119 | use App\Models\User; |
| 120 | use App\Repositories\UserRepositoryInterface; |
| 121 | use App\Services\UserService; |
| 122 | use PHPUnit\Framework\MockObject\MockObject; |
| 123 | use PHPUnit\Framework\TestCase; |
| 124 | |
| 125 | final class UserServiceTest extends TestCase |
| 126 | { |
| 127 | private UserRepositoryInterface&MockObject $users; |
| 128 | private UserService $service; |
| 129 | |
| 130 | protected function setUp(): void |
| 131 | { |
| 132 | parent::setUp(); |
| 133 | $this->users = $this->createMock(UserRepositoryInterface::class); |
| 134 | $this->service = new UserService($this->users); |
| 135 | } |
| 136 | |
| 137 | public function testCreateHashesPassword(): void |
| 138 | { |
| 139 | $dto = new CreateUserDTO('Alice', 'alice@example.com', 'secret'); |
| 140 | $user = new User(['name' => 'Alice', 'email' => 'alice@example.com']); |
| 141 | |
| 142 | $this->users |
| 143 | ->expects($this->once()) |
| 144 | ->method('create') |
| 145 | ->willReturn($user); |
| 146 | |
| 147 | $r |