mcpField
P
php-specialist

php-specialist

github.com/pixel-process-ug开发382 次安装34 周前更新
代码仓库

关于 php-specialist

面向编写、审查或重构 PHP 8.x 代码的开发者技能,涵盖现代语言特性、PSR 标准、Composer、静态分析和 SOLID 设计指导。

主要功能

  1. 01PHP 8.x 语言特性指导
  2. 02PSR 标准与 Composer 实践
  3. 03PHPStan 和 Psalm 静态分析
  4. 04使用 PHP CS Fixer 或 Pint 检查风格
  5. 05类型安全与 SOLID 设计模式

适用场景

  1. 01从定义接口开始开发 PHP 功能
  2. 02重构代码以增强类型安全
  3. 03检查 Composer 依赖与代码质量

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/pixel-process-ug/superkit-agents --skill php-specialist

安装后在 Claude Code 中输入/php-specialist确认已加载。

详细介绍

PHP 专家

概述

编写现代、类型安全且易于维护的 PHP 8.x 代码,并遵循 PSR 标准和 SOLID 原则。本技能涵盖完整的现代 PHP 工具链:PHP 8.0 至 8.4 引入的语言特性、PSR 互操作标准、Composer 依赖管理、使用 PHPStan 和 Psalm 进行静态分析、使用 PHP CS Fixer 和 Pint 强制执行编码风格,以及利用类型系统在编译时而非运行时确保正确性的架构模式。

在任何框架或独立环境中编写、审查或重构 PHP 代码时,都应运用此技能。

多阶段流程

阶段 1:环境评估
  1. 从 composer.json -> require.php 确认 PHP 版本
  2. 检查 composer.json 中的自动加载策略(PSR-4 命名空间)
  3. 检查静态分析配置(phpstan.neon、psalm.xml)
  4. 确认编码标准工具(pint.json、.php-cs-fixer.php)
  5. 梳理现有模式:枚举、DTO、值对象、接口

停止 — 未确认 PHP 版本和自动加载策略前,不要编写代码。

阶段 2:设计
  1. 在实现之前定义接口和契约
  2. 使用只读属性设计值对象和 DTO
  3. 在适用时将领域概念映射为有值枚举
  4. 规划领域的异常层级
  5. 确定依赖注入的切入点

停止 — 未为关键边界定义接口前,不要开始实现。

阶段 3:实现
  1. 先编写接口——先定义契约,再编写具体类
  2. 使用构造函数属性提升、只读属性、联合类型和交叉类型
  3. 优先使用 match 表达式而非 switch;使用命名参数以提高可读性
  4. 利用一等可调用语法进行函数式组合
  5. 在每个类的边界处应用 SOLID 原则

停止 — 不要在任何 PHP 文件中省略 strict_types 声明。

阶段 4:质量保证
  1. 将 PHPStan 运行到可达到的最高级别(目标级别 9)
  2. 使用 PHP CS Fixer 或 Laravel Pint 强制执行编码风格
  3. 检查类型覆盖率——未经说明,不得使用 mixed
  4. 检查是否违反 SOLID 原则或存在代码异味
  5. 确认 Composer 自动加载已优化(--classmap-authoritative)

PHP 版本特性决策表

特性最低版本使用时机
构造函数属性提升8.0任何包含构造函数参数的类
命名参数8.0有 3 个或更多参数的函数,或包含布尔标记的函数
Match 表达式8.0任何 switch 语句(严格匹配并返回值)
联合类型8.0参数可接受多种类型
有值枚举8.1任何包含带值命名常量的集合
只读属性8.1不可变 DTO、值对象
Fiber8.1异步框架(很少直接使用)
一等可调用对象8.1函数式组合、array_map/filter
只读类8.2全部为只读属性的 DTO(简写)
DNF 类型8.2复杂的联合类型与交叉类型组合
Override 属性8.3重写父类方法时(安全检查)
属性钩子8.4无需单独方法即可实现计算属性

现代 PHP 8.x 特性

枚举(PHP 8.1+)
// 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 8.1 / 8.2)
// 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;
    }
}
构造函数属性提升
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;
    }
}
命名参数
// 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);
Match 表达式
// 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),
};
联合类型和交叉类型
// 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 8.1+)
// 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();
Fiber(PHP 8.1+)
// 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 it

PSR 标准

PSR名称相关性
PSR-1基础编码标准基准要求:<?php 标签、UTF-8、命名空间/类约定
PSR-4自动加载在 composer.json 中将命名空间映射到目录 — 必须遵循
PSR-7HTTP 消息接口用于中间件管道的不可变请求/响应对象
PSR-11容器接口依赖注入容器互操作性
PSR-12扩展编码风格取代 PSR-2:格式、空格、声明
PSR-15HTTP 服务端中间件MiddlewareInterface 和 RequestHandlerInterface
PSR-17HTTP 工厂创建 PSR-7 对象(RequestFactory、ResponseFactory)
PSR-18HTTP 客户端用于互操作 HTTP 客户端的 ClientInterface
PSR-4 自动加载
{
    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Domain\\": "src/Domain/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    }
}

规则:命名空间的每个部分都与目录一一对应。App\Http\Controllers\UserController 位于 app/Http/Controllers/UserController.php。

Composer 依赖管理

基本命令
命令用途
composer require package/name添加生产依赖
composer require package/name --dev添加开发依赖
composer update --dry-run预览将发生的更改
composer why package/name显示安装某个包的原因
composer audit检查已知安全漏洞
composer bump将版本约束更新为已安装的版本
composer validate --strict验证 composer.json 和 composer.lock
最佳实践
  • 始终提交 composer.lock — 确保在不同环境中可重复安装
  • 使用 ^(插入符)约束:"laravel/framework": "^12.0" 允许次要版本/补丁版本更新
  • 分开管理开发依赖:测试、静态分析和调试工具放入 require-dev
  • 在 CI 中运行 composer audit,以发现已知漏洞
  • 在生产环境中使用 composer dump-autoload --classmap-authoritative 提升速度

静态分析

PHPStan 等级
等级检查内容
0基础检查:未定义变量、未知类、错误的函数调用
1+ 可能未定义的变量、$this 上的未知方法
2+ 所有表达式上的未知方法(不只是 $this)
3+ 验证返回类型
4+ 死代码、始终为真/假的条件
5+ 函数调用的参数类型
6+ 报告缺失的类型提示
7+ 全面检查联合类型
8+ 严格检查可空类型
9+ 禁止使用未显式处理的 mixed 类型
PHPStan 配置
# 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
PHP CS Fixer / Pint
// .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'])
    );

对于 Laravel 项目,使用带有 pint.json 预设的 Pint — 它封装了采用 Laravel 特定默认设置的 PHP CS Fixer。

PHP 中的 SOLID 原则

原则指导方针PHP 机制
S — 单一职责每个类只有一个变更理由Action 类、小型服务
O — 开闭原则无需修改源代码即可扩展行为接口、策略模式、枚举
L — 里氏替换原则子类型必须能够替换基类型协变返回类型、逆变参数
I — 接口隔离原则客户端只依赖其使用的方法小型、专注的接口
D — 依赖倒置原则依赖抽象而非具体实现构造函数注入、接口绑定
依赖倒置示例
// 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);
    }
}

错误处理模式

自定义异常层级
// 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,
        ));
    }
}
Result 模式(将错误作为值)
/** @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);
}

类型安全模式

通过只读类实现品牌类型/不透明类型
// 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 { /* ... */ }
通过 PHPStan 注解实现泛型集合
/**
 * @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);
    }
}

反模式 / 常见错误

反模式失败原因应采取的做法
将 mixed 用作逃生口类型安全网存在漏洞使用联合类型或泛型缩小类型范围
使用字符串表示类型拼写错误会导致运行时错误使用有底层值的枚举表示具名常量
上帝类(职责过多)难以测试、耦合度高拆分为 Action 类
抑制静态分析隐藏真正的错误修复问题;只有在说明原因后才添加 @phpstan-ignore
缺少 declare(strict_types=1)类型会被静默强制转换,从而产生错误添加到每个 PHP 文件中
使用数组结构表示领域数据缺少 IDE 支持,也没有类型安全保障使用只读 DTO 或值对象
服务定位器(在逻辑中使用 app())依赖关系隐藏,难以测试使用构造函数注入
宽泛捕获 \Exception会吞掉意料之外的错误捕获特定的异常类型
可变值对象共享状态会导致错误使用 readonly 类,并返回新实例
忽略 composer audit生产环境中存在已知漏洞在 CI 中运行,并将失败视为构建失败
深层继承(3 层以上)脆弱基类问题优先使用组合和接口
类未标记为 final可能被意外扩展默认使用 final,仅在有意设计为可扩展时开放

防止自我合理化

  • 不要因为“这只是一个小脚本”而跳过 declare(strict_types=1)——所有地方都要添加。
  • 不要在没有注释说明为何无法使用更窄类型的情况下使用 mixed。
  • 不要在没有书面说明代码为何正确的情况下抑制 PHPStan 错误。
  • 不要在业务逻辑中使用服务定位器模式(app()),即使是在 Laravel 中也是如此。
  • 不要因为“只有一种实现”而跳过关键边界的接口——以后会有第二种实现。

文档查询(Context7)

使用 mcp__context7__resolve-library-id,然后使用 mcp__context7__query-docs 获取最新文档。返回的文档优先于记忆中的知识。

  • php — 用于语言特性、内置函数或 PHP 8.x 语法
  • composer — 用于包管理、自动加载或脚本配置

集成点

技能连接方式
laravel-specialistPHP 8.x 特性支持 Eloquent 转换、枚举、只读 DTO 和类型化集合
senior-backendSOLID 架构、接口驱动设计、错误处理模式
test-driven-development使用强类型断言进行 PHPUnit/Pest 测试
clean-codeSOLID、DRY,以及 PHP 层面的代码异味检测
security-review输入验证、类型强制转换风险、依赖漏洞
laravel-boost通过指南和 MCP 工具提升 AI 生成 PHP 代码的质量

技能类型

灵活 — 根据工作范围调整各阶段的流程。单个函数可能只需要第 3 和第 4 阶段。新模块或软件包应遵循全部四个阶段。无论工作范围如何,以下要求都不可妥协:declare(strict_types=1)、符合项目配置级别的 PHPStan 要求,以及 PSR-4 自动加载。

评论

支持 Markdown