php-specialist
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePHP Specialist
PHP专家
Overview
概述
Write modern, type-safe, and maintainable PHP 8.x code adhering to PSR standards and SOLID principles. This skill covers the full modern PHP toolchain: language features introduced in PHP 8.0 through 8.4, PSR interoperability standards, Composer dependency management, static analysis with PHPStan and Psalm, coding style enforcement with PHP CS Fixer and Pint, and architectural patterns that leverage the type system for correctness at compile time rather than runtime.
Apply this skill whenever PHP code is being written, reviewed, or refactored in any framework or standalone context.
编写符合PSR标准和SOLID原则的现代、类型安全、可维护的PHP 8.x代码。本技能覆盖完整的现代PHP工具链:PHP 8.0至8.4版本引入的语言特性、PSR互操作性标准、Composer依赖管理、基于PHPStan和Psalm的静态分析、通过PHP CS Fixer和Pint落地编码规范,以及利用类型系统在编译期而非运行期保障正确性的架构模式。
无论在任何框架或独立场景下编写、评审或重构PHP代码时,均可应用本技能。
Multi-Phase Process
多阶段流程
Phase 1: Environment Assessment
阶段1:环境评估
- Identify PHP version from ->
composer.jsonrequire.php - Review for autoloading strategy (PSR-4 namespaces)
composer.json - Check for static analysis configuration (,
phpstan.neon)psalm.xml - Identify coding standard tool (,
pint.json).php-cs-fixer.php - Catalog existing patterns: enums, DTOs, value objects, interfaces
STOP — Do NOT write code without knowing the PHP version and autoloading strategy.
- 从的
composer.json字段确认PHP版本require.php - 检查中的自动加载策略(PSR-4命名空间)
composer.json - 确认静态分析配置是否存在(、
phpstan.neon)psalm.xml - 识别使用的编码规范工具(、
pint.json).php-cs-fixer.php - 梳理现有代码模式:枚举、DTO、值对象、接口
停止 — 未明确PHP版本和自动加载策略前,不要编写任何代码。
Phase 2: Design
阶段2:设计
- Define interfaces and contracts before implementations
- Design value objects and DTOs with readonly properties
- Map domain concepts to backed enums where applicable
- Plan exception hierarchy for the domain
- Identify seams for dependency injection
STOP — Do NOT implement without interfaces defined for key boundaries.
- 先定义接口和契约,再编写实现逻辑
- 使用只读属性设计值对象和DTO
- 合适的领域概念映射为回退枚举(backed enums)
- 规划领域对应的异常层级
- 识别依赖注入的接缝点
停止 — 未为核心边界定义接口前,不要开始实现。
Phase 3: Implementation
阶段3:实现
- Write interfaces first — contracts before concrete classes
- Implement with constructor promotion, readonly properties, union/intersection types
- Use match expressions over switch; named arguments for clarity
- Leverage first-class callable syntax for functional composition
- Apply SOLID principles at every class boundary
STOP — Do NOT skip strict_types declaration in any PHP file.
- 优先编写接口:契约早于具体类
- 实现时使用构造器属性提升、只读属性、联合/交集类型
- 优先使用match表达式而非switch;使用命名参数提升可读性
- 利用一等可调用语法实现函数式组合
- 在每个类边界应用SOLID原则
停止 — 任何PHP文件都不能缺少strict_types声明。
Phase 4: Quality Assurance
阶段4:质量保障
- Run PHPStan at maximum achievable level (target level 9)
- Enforce coding style with PHP CS Fixer or Laravel Pint
- Verify type coverage — no without justification
mixed - Review for SOLID violations and code smells
- Confirm Composer autoload is optimized ()
--classmap-authoritative
- 以可达到的最高级别运行PHPStan(目标级别9)
- 通过PHP CS Fixer或Laravel Pint强制执行编码规范
- 验证类型覆盖率:无合理理由不得使用类型
mixed - 检查是否违反SOLID原则、是否存在代码坏味道
- 确认Composer自动加载已优化()
--classmap-authoritative
PHP Version Feature Decision Table
PHP版本特性决策表
| Feature | Minimum Version | Use When |
|---|---|---|
| Constructor promotion | 8.0 | Any class with constructor parameters |
| Named arguments | 8.0 | Functions with 3+ params or boolean flags |
| Match expressions | 8.0 | Any switch statement (strict, returns value) |
| Union types | 8.0 | Parameter accepts multiple types |
| Backed enums | 8.1 | Any set of named constants with values |
| Readonly properties | 8.1 | Immutable DTOs, value objects |
| Fibers | 8.1 | Async frameworks (rarely used directly) |
| First-class callables | 8.1 | Functional composition, array_map/filter |
| Readonly classes | 8.2 | All-readonly DTOs (shorthand) |
| DNF types | 8.2 | Complex union + intersection combinations |
| Override attribute | 8.3 | Overriding parent methods (safety check) |
| Property hooks | 8.4 | Computed properties without separate methods |
| 特性 | 最低版本 | 使用场景 |
|---|---|---|
| 构造器属性提升 | 8.0 | 所有带构造参数的类 |
| 命名参数 | 8.0 | 参数≥3个或包含布尔标志位的函数 |
| Match表达式 | 8.0 | 所有switch语句场景(严格匹配、支持返回值) |
| 联合类型 | 8.0 | 参数支持多种类型的场景 |
| 回退枚举 | 8.1 | 所有带值的命名常量集合 |
| 只读属性 | 8.1 | 不可变DTO、值对象 |
| Fibers | 8.1 | 异步框架(极少直接使用) |
| 一等可调用对象 | 8.1 | 函数式组合、array_map/filter |
| 只读类 | 8.2 | 全属性只读的DTO(简化写法) |
| DNF类型 | 8.2 | 复杂的联合+交集类型组合 |
| Override属性 | 8.3 | 重写父类方法时的安全检查 |
| 属性钩子 | 8.4 | 无需单独方法实现计算属性 |
Modern PHP 8.x Features
现代PHP 8.x特性
Enums (PHP 8.1+)
Enums (PHP 8.1+)
php
// Backed enum with methods — replaces class constants and magic strings
enum OrderStatus: string
{
case Draft = 'draft';
case Pending = 'pending';
case Confirmed = 'confirmed';
case Shipped = 'shipped';
case Delivered = 'delivered';
case Cancelled = 'cancelled';
public function label(): string
{
return match ($this) {
self::Draft => 'Draft',
self::Pending => 'Pending Review',
self::Confirmed => 'Confirmed',
self::Shipped => 'Shipped',
self::Delivered => 'Delivered',
self::Cancelled => 'Cancelled',
};
}
public function isFinal(): bool
{
return in_array($this, [self::Delivered, self::Cancelled], true);
}
/** @return list<self> */
public static function active(): array
{
return array_filter(self::cases(), fn (self $s) => ! $s->isFinal());
}
}php
// 带方法的回退枚举——替代类常量和魔法字符串
enum OrderStatus: string
{
case Draft = 'draft';
case Pending = 'pending';
case Confirmed = 'confirmed';
case Shipped = 'shipped';
case Delivered = 'delivered';
case Cancelled = 'cancelled';
public function label(): string
{
return match ($this) {
self::Draft => 'Draft',
self::Pending => 'Pending Review',
self::Confirmed => 'Confirmed',
self::Shipped => 'Shipped',
self::Delivered => 'Delivered',
self::Cancelled => 'Cancelled',
};
}
public function isFinal(): bool
{
return in_array($this, [self::Delivered, self::Cancelled], true);
}
/** @return list<self> */
public static function active(): array
{
return array_filter(self::cases(), fn (self $s) => ! $s->isFinal());
}
}Readonly Properties and Classes (PHP 8.1 / 8.2)
只读属性和只读类 (PHP 8.1 / 8.2)
php
// Readonly class — all properties are implicitly readonly
readonly class Money
{
public function __construct(
public int $amount,
public string $currency,
) {}
public function add(self $other): self
{
if ($this->currency !== $other->currency) {
throw new CurrencyMismatchException($this->currency, $other->currency);
}
return new self($this->amount + $other->amount, $this->currency);
}
public function isPositive(): bool
{
return $this->amount > 0;
}
}php
// 只读类——所有属性隐式为只读
readonly class Money
{
public function __construct(
public int $amount,
public string $currency,
) {}
public function add(self $other): self
{
if ($this->currency !== $other->currency) {
throw new CurrencyMismatchException($this->currency, $other->currency);
}
return new self($this->amount + $other->amount, $this->currency);
}
public function isPositive(): bool
{
return $this->amount > 0;
}
}Constructor Promotion
构造器属性提升
php
class CreateUserAction
{
public function __construct(
private readonly UserRepository $users,
private readonly Hasher $hasher,
private readonly EventDispatcher $events,
) {}
public function execute(CreateUserData $data): User
{
$user = $this->users->create([
'name' => $data->name,
'email' => $data->email,
'password' => $this->hasher->make($data->password),
]);
$this->events->dispatch(new UserCreated($user));
return $user;
}
}php
class CreateUserAction
{
public function __construct(
private readonly UserRepository $users,
private readonly Hasher $hasher,
private readonly EventDispatcher $events,
) {}
public function execute(CreateUserData $data): User
{
$user = $this->users->create([
'name' => $data->name,
'email' => $data->email,
'password' => $this->hasher->make($data->password),
]);
$this->events->dispatch(new UserCreated($user));
return $user;
}
}Named Arguments
命名参数
php
// Improves readability for functions with many parameters or boolean flags
$user = User::create(
name: $request->name,
email: $request->email,
isAdmin: false,
sendWelcomeEmail: true,
);
// Particularly valuable with optional parameters
$response = Http::timeout(seconds: 30)
->retry(times: 3, sleepMilliseconds: 500, throw: true)
->get($url);php
// 提升多参数或带布尔标志位函数的可读性
$user = User::create(
name: $request->name,
email: $request->email,
isAdmin: false,
sendWelcomeEmail: true,
);
// 对可选参数尤其有用
$response = Http::timeout(seconds: 30)
->retry(times: 3, sleepMilliseconds: 500, throw: true)
->get($url);Match Expressions
Match表达式
php
// match is strict (===), exhaustive, and returns a value
$discount = match (true) {
$total >= 10000 => 0.15,
$total >= 5000 => 0.10,
$total >= 1000 => 0.05,
default => 0.00,
};
// Replaces switch with no fall-through risk
$handler = match ($event::class) {
OrderPlaced::class => new HandleOrderPlaced(),
PaymentFailed::class => new HandlePaymentFailed(),
default => throw new UnhandledEventException($event),
};php
// match是严格匹配(===)、覆盖全场景、支持返回值
$discount = match (true) {
$total >= 10000 => 0.15,
$total >= 5000 => 0.10,
$total >= 1000 => 0.05,
default => 0.00,
};
// 替代switch,无穿透风险
$handler = match ($event::class) {
OrderPlaced::class => new HandleOrderPlaced(),
PaymentFailed::class => new HandlePaymentFailed(),
default => throw new UnhandledEventException($event),
};Union and Intersection Types
联合类型和交集类型
php
// Union type — accepts either type
function findUser(int|string $identifier): User
{
return is_int($identifier)
? User::findOrFail($identifier)
: User::where('email', $identifier)->firstOrFail();
}
// Intersection type — must satisfy all interfaces
function processLoggableEntity(Loggable&Serializable $entity): void
{
$entity->log();
$data = $entity->serialize();
}
// DNF types (PHP 8.2) — combine union and intersection
function handle((Renderable&Countable)|string $content): string
{
if (is_string($content)) {
return $content;
}
return $content->render();
}php
// 联合类型——接受任意一种指定类型
function findUser(int|string $identifier): User
{
return is_int($identifier)
? User::findOrFail($identifier)
: User::where('email', $identifier)->firstOrFail();
}
// 交集类型——必须满足所有接口要求
function processLoggableEntity(Loggable&Serializable $entity): void
{
$entity->log();
$data = $entity->serialize();
}
// DNF类型 (PHP 8.2) —— 组合联合和交集类型
function handle((Renderable&Countable)|string $content): string
{
if (is_string($content)) {
return $content;
}
return $content->render();
}First-Class Callable Syntax (PHP 8.1+)
一等可调用语法 (PHP 8.1+)
php
// Create closures from named functions
$slugify = Str::slug(...);
$titles = array_map($slugify, $names);
// Method references
$validator = Validator::make(...);
// Useful for pipeline / collection patterns
$activeUsers = collect($users)
->filter(UserPolicy::isActive(...))
->map(UserTransformer::toArray(...))
->values();php
// 从命名函数创建闭包
$slugify = Str::slug(...);
$titles = array_map($slugify, $names);
// 方法引用
$validator = Validator::make(...);
// 适用于流水线/集合模式
$activeUsers = collect($users)
->filter(UserPolicy::isActive(...))
->map(UserTransformer::toArray(...))
->values();Fibers (PHP 8.1+)
Fibers (PHP 8.1+)
php
// Fibers enable cooperative multitasking — foundation for async frameworks
$fiber = new Fiber(function (): void {
$value = Fiber::suspend('paused');
echo "Resumed with: {$value}";
});
$result = $fiber->start(); // Returns 'paused'
$fiber->resume('hello world'); // Prints: "Resumed with: hello world"
// Practical use: async HTTP client internals, event loops (Revolt, ReactPHP)
// Application developers rarely use Fiber directly — frameworks abstract itphp
// Fibers支持协作式多任务——是异步框架的基础
$fiber = new Fiber(function (): void {
$value = Fiber::suspend('paused');
echo "Resumed with: {$value}";
});
$result = $fiber->start(); // 返回 'paused'
$fiber->resume('hello world'); // 输出: "Resumed with: hello world"
// 实际应用场景:异步HTTP客户端底层、事件循环(Revolt、ReactPHP)
// 应用开发者极少直接使用Fiber——框架会做封装PSR Standards
PSR标准
| PSR | Name | Relevance |
|---|---|---|
| PSR-1 | Basic Coding Standard | Baseline: |
| PSR-4 | Autoloading | Map namespaces to directories in |
| PSR-7 | HTTP Message Interfaces | Immutable request/response objects for middleware pipelines |
| PSR-11 | Container Interface | Dependency injection container interoperability |
| PSR-12 | Extended Coding Style | Supersedes PSR-2: formatting, spacing, declarations |
| PSR-15 | HTTP Server Middleware | |
| PSR-17 | HTTP Factories | Create PSR-7 objects (RequestFactory, ResponseFactory) |
| PSR-18 | HTTP Client | |
| PSR | 名称 | 相关性 |
|---|---|---|
| PSR-1 | 基础编码标准 | 基线要求: |
| PSR-4 | 自动加载 | 在 |
| PSR-7 | HTTP消息接口 | 中间件流水线使用的不可变请求/响应对象 |
| PSR-11 | 容器接口 | 依赖注入容器互操作性标准 |
| PSR-12 | 扩展编码风格 | 替代PSR-2:格式化、空格、声明规范 |
| PSR-15 | HTTP服务端中间件 | |
| PSR-17 | HTTP工厂 | 创建PSR-7对象的标准(RequestFactory、ResponseFactory) |
| PSR-18 | HTTP客户端 | 可互操作HTTP客户端的 |
PSR-4 Autoloading
PSR-4自动加载
json
{
"autoload": {
"psr-4": {
"App\\": "app/",
"Domain\\": "src/Domain/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}
}Rule: namespace segment maps 1:1 to directory. lives at .
App\Http\Controllers\UserControllerapp/Http/Controllers/UserController.phpjson
{
"autoload": {
"psr-4": {
"App\\": "app/",
"Domain\\": "src/Domain/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}
}规则:命名空间段与目录1:1映射。对应的文件路径为。
App\Http\Controllers\UserControllerapp/Http/Controllers/UserController.phpComposer Dependency Management
Composer依赖管理
Essential Commands
核心命令
| Command | Purpose |
|---|---|
| Add production dependency |
| Add development dependency |
| Preview what would change |
| Show why a package is installed |
| Check for known security vulnerabilities |
| Update version constraints to installed versions |
| Validate |
| 命令 | 用途 |
|---|---|
| 添加生产环境依赖 |
| 添加开发环境依赖 |
| 预览更新内容,不实际执行 |
| 查看某个包被安装的原因 |
| 检查已知安全漏洞 |
| 将版本约束更新为已安装的版本 |
| 校验 |
Best Practices
最佳实践
- Always commit — reproducible installs across environments
composer.lock - Use (caret) constraints:
^allows minor/patch updates"laravel/framework": "^12.0" - Separate dev dependencies: testing, static analysis, and debug tools go in
require-dev - Run in CI to catch known vulnerabilities
composer audit - Use in production for speed
composer dump-autoload --classmap-authoritative
- 始终提交——保障多环境安装的一致性
composer.lock - 使用(插入符)约束:
^允许小版本和补丁版本更新"laravel/framework": "^12.0" - 分离开发依赖:测试、静态分析、调试工具放在中
require-dev - 在CI中运行,提前发现已知漏洞
composer audit - 生产环境使用提升加载速度
composer dump-autoload --classmap-authoritative
Static Analysis
静态分析
PHPStan Levels
PHPStan级别
| Level | What It Checks |
|---|---|
| 0 | Basic: undefined variables, unknown classes, wrong function calls |
| 1 | + possibly undefined variables, unknown methods on |
| 2 | + unknown methods on all expressions (not just |
| 3 | + return types verified |
| 4 | + dead code, always-true/false conditions |
| 5 | + argument types of function calls |
| 6 | + missing typehints reported |
| 7 | + union types checked exhaustively |
| 8 | + nullable types checked strictly |
| 9 | + |
| 级别 | 检查内容 |
|---|---|
| 0 | 基础检查:未定义变量、未知类、错误的函数调用 |
| 1 | 新增:可能未定义的变量、 |
| 2 | 新增:所有表达式上的未知方法(不限于 |
| 3 | 新增:返回类型校验 |
| 4 | 新增:死代码、恒真/恒假条件 |
| 5 | 新增:函数调用的参数类型校验 |
| 6 | 新增:上报缺失的类型提示 |
| 7 | 新增:联合类型全场景覆盖检查 |
| 8 | 新增:可空类型严格检查 |
| 9 | 新增:无显式处理时禁止使用 |
PHPStan Configuration
PHPStan配置
neon
undefinedneon
undefinedphpstan.neon
phpstan.neon
parameters:
level: 9
paths:
- app
- src
excludePaths:
- app/Console/Kernel.php
ignoreErrors: []
checkMissingIterableValueType: true
checkGenericClassInNonGenericObjectType: true
includes:
- vendor/larastan/larastan/extension.neon # Laravel-specific rules
undefinedparameters:
level: 9
paths:
- app
- src
excludePaths:
- app/Console/Kernel.php
ignoreErrors: []
checkMissingIterableValueType: true
checkGenericClassInNonGenericObjectType: true
includes:
- vendor/larastan/larastan/extension.neon # Laravel专属规则
undefinedPHP CS Fixer / Pint
PHP CS Fixer / Pint
php
// .php-cs-fixer.php — for non-Laravel projects
return (new PhpCsFixer\Config())
->setRules([
'@PER-CS' => true,
'strict_types' => true,
'declare_strict_types' => true,
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'no_unused_imports' => true,
'trailing_comma_in_multiline' => true,
])
->setFinder(
PhpCsFixer\Finder::create()->in([__DIR__ . '/src', __DIR__ . '/tests'])
);For Laravel projects, use Pint with a preset — it wraps PHP CS Fixer with Laravel-specific defaults.
pint.jsonphp
// .php-cs-fixer.php —— 适用于非Laravel项目
return (new PhpCsFixer\Config())
->setRules([
'@PER-CS' => true,
'strict_types' => true,
'declare_strict_types' => true,
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'no_unused_imports' => true,
'trailing_comma_in_multiline' => true,
])
->setFinder(
PhpCsFixer\Finder::create()->in([__DIR__ . '/src', __DIR__ . '/tests'])
);Laravel项目可使用Pint配合预设——它封装了PHP CS Fixer,提供Laravel专属的默认配置。
pint.jsonSOLID Principles in PHP
PHP中的SOLID原则
| Principle | Guideline | PHP Mechanism |
|---|---|---|
| S — Single Responsibility | One reason to change per class | Action classes, small services |
| O — Open/Closed | Extend behavior without modifying source | Interfaces, strategy pattern, enums |
| L — Liskov Substitution | Subtypes must be substitutable for base types | Covariant returns, contravariant params |
| I — Interface Segregation | Clients depend only on methods they use | Small, focused interfaces |
| D — Dependency Inversion | Depend on abstractions, not concretions | Constructor injection, interface bindings |
| 原则 | 指导规则 | PHP实现机制 |
|---|---|---|
| S — 单一职责 | 每个类只有一个变更理由 | 动作类、小型服务 |
| O — 开闭原则 | 扩展行为时无需修改源代码 | 接口、策略模式、枚举 |
| L — 里氏替换 | 子类型必须可以替换父类型 | 协变返回、逆变参数 |
| I — 接口隔离 | 客户端仅依赖自身使用的方法 | 小型、聚焦的接口 |
| D — 依赖倒置 | 依赖抽象而非具体实现 | 构造器注入、接口绑定 |
Dependency Inversion Example
依赖倒置示例
php
// Contract (abstraction)
interface PaymentGateway
{
public function charge(Money $amount, PaymentMethod $method): PaymentResult;
}
// Implementation (concretion) — can be swapped without changing consumers
final class StripeGateway implements PaymentGateway
{
public function __construct(private readonly StripeClient $client) {}
public function charge(Money $amount, PaymentMethod $method): PaymentResult
{
// Stripe-specific logic
}
}
// Consumer depends on abstraction only
final class ProcessPaymentAction
{
public function __construct(private readonly PaymentGateway $gateway) {}
public function execute(Order $order): PaymentResult
{
return $this->gateway->charge($order->total, $order->paymentMethod);
}
}php
// 契约(抽象)
interface PaymentGateway
{
public function charge(Money $amount, PaymentMethod $method): PaymentResult;
}
// 实现(具体类)——无需修改消费者即可替换
final class StripeGateway implements PaymentGateway
{
public function __construct(private readonly StripeClient $client) {}
public function charge(Money $amount, PaymentMethod $method): PaymentResult
{
// Stripe专属逻辑
}
}
// 消费者仅依赖抽象
final class ProcessPaymentAction
{
public function __construct(private readonly PaymentGateway $gateway) {}
public function execute(Order $order): PaymentResult
{
return $this->gateway->charge($order->total, $order->paymentMethod);
}
}Error Handling Patterns
错误处理模式
Custom Exception Hierarchy
自定义异常层级
php
// Base domain exception
abstract class DomainException extends \RuntimeException {}
// Specific exceptions with factory methods
final class InsufficientFundsException extends DomainException
{
public static function forAccount(Account $account, Money $required): self
{
return new self(sprintf(
'Account %s has %d %s but %d %s is required.',
$account->id,
$account->balance->amount,
$account->balance->currency,
$required->amount,
$required->currency,
));
}
}php
// 领域基础异常
abstract class DomainException extends \RuntimeException {}
// 带工厂方法的具体异常
final class InsufficientFundsException extends DomainException
{
public static function forAccount(Account $account, Money $required): self
{
return new self(sprintf(
'Account %s has %d %s but %d %s is required.',
$account->id,
$account->balance->amount,
$account->balance->currency,
$required->amount,
$required->currency,
));
}
}Result Pattern (Error as Value)
结果模式(错误作为值)
php
/** @template T */
readonly class Result
{
/** @param T|null $value */
private function __construct(
public bool $ok,
public mixed $value = null,
public ?string $error = null,
) {}
/** @param T $value */
public static function success(mixed $value): self
{
return new self(ok: true, value: $value);
}
public static function failure(string $error): self
{
return new self(ok: false, error: $error);
}
}
// Usage — caller must handle both paths
$result = $action->execute($data);
if (! $result->ok) {
return response()->json(['error' => $result->error], 422);
}php
/** @template T */
readonly class Result
{
/** @param T|null $value */
private function __construct(
public bool $ok,
public mixed $value = null,
public ?string $error = null,
) {}
/** @param T $value */
public static function success(mixed $value): self
{
return new self(ok: true, value: $value);
}
public static function failure(string $error): self
{
return new self(ok: false, error: $error);
}
}
// 用法——调用方必须处理两种分支
$result = $action->execute($data);
if (! $result->ok) {
return response()->json(['error' => $result->error], 422);
}Type Safety Patterns
类型安全模式
Branded / Opaque Types via Readonly Classes
基于只读类的品牌/不透明类型
php
// Prevent accidental mixing of IDs from different entities
readonly class UserId
{
public function __construct(public int $value) {}
public function equals(self $other): bool
{
return $this->value === $other->value;
}
}
readonly class OrderId
{
public function __construct(public int $value) {}
}
// Compiler prevents: processOrder(new UserId(1)) when OrderId is expected
function processOrder(OrderId $orderId): void { /* ... */ }php
// 避免不同实体的ID意外混用
readonly class UserId
{
public function __construct(public int $value) {}
public function equals(self $other): bool
{
return $this->value === $other->value;
}
}
readonly class OrderId
{
public function __construct(public int $value) {}
}
// 编译器会拦截:当期望OrderId时传入processOrder(new UserId(1))的调用
function processOrder(OrderId $orderId): void { /* ... */ }Generic Collections via PHPStan Annotations
基于PHPStan注解的泛型集合
php
/**
* @template T
* @implements \IteratorAggregate<int, T>
*/
final class TypedCollection implements \IteratorAggregate, \Countable
{
/** @param list<T> $items */
public function __construct(private array $items = []) {}
/** @param T $item */
public function add(mixed $item): void
{
$this->items[] = $item;
}
/** @return \ArrayIterator<int, T> */
public function getIterator(): \ArrayIterator
{
return new \ArrayIterator($this->items);
}
public function count(): int
{
return count($this->items);
}
}php
/**
* @template T
* @implements \IteratorAggregate<int, T>
*/
final class TypedCollection implements \IteratorAggregate, \Countable
{
/** @param list<T> $items */
public function __construct(private array $items = []) {}
/** @param T $item */
public function add(mixed $item): void
{
$this->items[] = $item;
}
/** @return \ArrayIterator<int, T> */
public function getIterator(): \ArrayIterator
{
return new \ArrayIterator($this->items);
}
public function count(): int
{
return count($this->items);
}
}Anti-Patterns / Common Mistakes
反模式/常见错误
| Anti-Pattern | Why It Fails | What To Do Instead |
|---|---|---|
Using | Holes in type safety net | Narrow with union types or generics |
| Stringly-typed code | Runtime errors from typos | Use backed enums for named constants |
| God classes (many responsibilities) | Untestable, high coupling | Split into Action classes |
| Suppressing static analysis | Hides real bugs | Fix the issue, add |
Missing | Silent type coercion bugs | Add to every PHP file |
| Array-shaped domain data | No IDE support, no type safety | Use readonly DTOs or value objects |
Service locator ( | Hidden dependencies, untestable | Constructor injection |
Catching | Swallows unexpected errors | Catch specific exception types |
| Mutable value objects | Shared state bugs | Use |
Ignoring | Known vulnerabilities in production | Run in CI, treat as build failure |
| Deep inheritance (3+ levels) | Fragile base class problem | Prefer composition and interfaces |
Classes not marked | Unintended extension | Default to |
| 反模式 | 缺陷 | 替代方案 |
|---|---|---|
用 | 类型安全网存在漏洞 | 使用联合类型或泛型缩小类型范围 |
| 字符串类型代码 | 拼写错误导致运行时错误 | 使用回退枚举替代命名常量 |
| 上帝类(承担过多职责) | 无法测试、耦合度高 | 拆分为多个动作类 |
| 屏蔽静态分析告警 | 隐藏真实bug | 修复问题,仅在有合理解释时添加 |
缺少 | 隐式类型转换导致bug | 每个PHP文件都添加该声明 |
| 用数组承载领域数据 | 无IDE支持、无类型安全 | 使用只读DTO或值对象 |
服务定位器(逻辑中使用 | 依赖隐藏、无法测试 | 使用构造器注入 |
宽泛捕获 | 吞噬非预期错误 | 捕获特定的异常类型 |
| 可变值对象 | 共享状态导致bug | 使用 |
忽略 | 生产环境存在已知漏洞 | 在CI中运行,告警时阻断构建 |
| 深层继承(≥3层) | 基类脆弱问题 | 优先使用组合和接口 |
类未标记 | 非预期的扩展 | 默认使用 |
Anti-Rationalization Guards
反合理化约束
- Do NOT skip because "it's just a small script" -- add it everywhere.
declare(strict_types=1) - Do NOT use without a comment justifying why a narrower type is impossible.
mixed - Do NOT suppress PHPStan errors without a written explanation of why the code is correct.
- Do NOT use the service locator pattern () in business logic, even in Laravel.
app() - Do NOT skip interfaces for key boundaries because "there's only one implementation" -- there will be two.
- 不要因为“这只是个小脚本”就省略——所有文件都要添加。
declare(strict_types=1) - 不要在没有注释说明无法使用更窄类型的理由时使用。
mixed - 不要在没有书面解释代码正确性的前提下屏蔽PHPStan错误。
- 不要在业务逻辑中使用服务定位器模式(),即使是Laravel项目。
app() - 不要因为“只有一个实现”就省略核心边界的接口——未来总会有第二个实现。
Documentation Lookup (Context7)
文档查询(Context7)
Use then for up-to-date docs. Returned docs override memorized knowledge.
mcp__context7__resolve-library-idmcp__context7__query-docs- — for language features, built-in functions, or PHP 8.x syntax
php - — for package management, autoloading, or scripts configuration
composer
使用然后调用获取最新文档,返回的文档优先级高于记忆知识。
mcp__context7__resolve-library-idmcp__context7__query-docs- —— 查询语言特性、内置函数或PHP 8.x语法
php - —— 查询包管理、自动加载或脚本配置
composer
Integration Points
集成点
| Skill | How It Connects |
|---|---|
| PHP 8.x features power Eloquent casts, enums, readonly DTOs, and typed collections |
| SOLID architecture, interface-driven design, error handling patterns |
| PHPUnit/Pest testing with strong type assertions |
| SOLID, DRY, code smell detection at the PHP level |
| Input validation, type coercion risks, dependency vulnerabilities |
| AI-generated PHP code quality via guidelines and MCP tools |
| 技能 | 关联方式 |
|---|---|
| PHP 8.x特性支撑Eloquent类型转换、枚举、只读DTO和类型化集合 |
| SOLID架构、接口驱动设计、错误处理模式 |
| PHPUnit/Pest测试配合强类型断言 |
| PHP层面的SOLID、DRY、代码坏味道检测 |
| 输入校验、类型转换风险、依赖漏洞 |
| 通过规范和MCP工具提升AI生成PHP代码的质量 |
Skill Type
技能类型
FLEXIBLE — Adapt the process phases to the scope of work. A single function may need only Phase 3 and 4. A new module or package should follow all four phases. Non-negotiable regardless of scope: , PHPStan compliance at the project's configured level, and PSR-4 autoloading.
declare(strict_types=1)灵活适配 —— 根据工作范围调整流程阶段。单个函数可能只需要阶段3和4。新模块或包应该遵循全部四个阶段。无论范围如何都不能妥协的规则:、符合项目配置级别的PHPStan规范、PSR-4自动加载。
declare(strict_types=1)