mcpField
L
laravel-specialist

laravel-specialist

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

关于 laravel-specialist

这是一项用于设计、构建和维护 Laravel 应用的技能,涵盖架构、实现、测试与优化,并整合 Eloquent、Blade、Livewire、队列、事件和 Pest 的 Laravel 实践指南。

主要功能

  1. 01Laravel 项目与架构审查
  2. 02Eloquent 模型和关系
  3. 03Blade 与 Livewire 模式
  4. 04队列、作业、事件与中间件
  5. 05覆盖多层的 Pest 测试
  6. 06迁移、数据填充与 Artisan

适用场景

  1. 01规划新的 Laravel 应用
  2. 02审查现有项目架构
  3. 03构建数据模型和异步作业
  4. 04测试路由、数据库行为和用户流程

安装

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

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

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

详细介绍

Laravel 专家

概述

遵循框架约定和最佳实践,设计、构建并维护可用于生产环境的 Laravel 应用。此技能涵盖完整的 Laravel 生态系统:具有高级关联模式的 Eloquent ORM、Blade 模板和 Livewire 交互功能、队列与事件系统、中间件管道、服务提供者、各层级的 Pest 测试,以及用于迁移、填充数据和工厂的 Artisan 工具。

无论是从零开始开发还是在现有项目上进行开发,只要应用使用 Laravel 作为框架,就应运用此技能。

多阶段流程

阶段 1:发现上下文
  1. 确认 Laravel 版本(composer.json -> laravel/framework)
  2. 扫描 config/,了解已启用的包和自定义配置
  3. 梳理现有模型、关联关系和迁移历史
  4. 查看 routes/ 中的 API、Web、控制台和频道定义
  5. 列出已安装的第一方包(Sanctum、Horizon、Telescope、Pulse、Pennant、Scout、Cashier)
  6. 检查前端技术栈是否使用 Livewire、Inertia,或仅使用 Blade

停止 — 未确认 Laravel 版本和已安装的包之前,不要开始架构审查。

文档验证协议

[HARD-GATE] 如果不确定任何 Laravel API,请先验证,不要猜测。优先使用 mcp__context7__resolve-library-id,然后使用 mcp__context7__query-docs。备用方法:从 https://github.com/laravel/docs 获取文档。对于 Livewire、Pest、Inertia,请分别通过 context7 解析。返回的文档优先于记忆中的知识。

阶段 2:架构审查
  1. 确认目录结构符合 Laravel 约定(见下文相关章节)
  2. 评估服务提供者注册和延迟加载
  3. 检查中间件栈的顺序和分组
  4. 评估队列连接配置和工作进程拓扑
  5. 检查缓存策略(配置、路由、视图、应用级缓存)

停止 — 记录架构差距之前,不要开始实施。

阶段 3:实施
  1. 先编写迁移 — 数据库架构是事实来源
  2. 构建 Eloquent 模型,并定义关联关系、查询范围、类型转换和访问器
  3. 在专用的 Action 或 Service 类中实现业务逻辑
  4. 创建与路由绑定的控制器(单动作控制器或资源控制器)
  5. 添加用于验证的 Form Request,以及用于授权的 Policy
  6. 为异步工作流接入事件、监听器和作业

停止 — 不要跳过 Form Request 和 Policy。内联验证和授权属于反模式。

阶段 4:测试
  1. 为隔离逻辑(Action、值对象、类型转换)编写单元测试
  2. 为 HTTP 端点和中间件行为编写功能测试
  3. 使用 Laravel Dusk 为关键用户流程编写浏览器测试
  4. 使用 assertDatabaseHas、assertSoftDeleted 进行数据库断言
  5. 使用队列和事件伪造功能验证副作用

停止 — 所有层级的测试通过之前,不要进行优化。

阶段 5:优化
  1. 使用预加载消除 N+1 查询
  2. 缓存开销较大的计算结果,以及配置、路由和视图
  3. 为频繁查询的列创建索引;使用 EXPLAIN 进行验证
  4. 在开发环境中使用 Telescope 或 Debugbar 进行性能分析
  5. 配置 Horizon,以监控生产环境中的队列

Eloquent 模式

关联关系
关联关系方法反向关联使用场景
一对一hasOnebelongsTo用户 -> 个人资料
一对多hasManybelongsTo文章 -> 评论
多对多belongsToManybelongsToMany用户 <-> 角色(中间表)
穿透式一对多hasManyThrough—国家 -> 文章(通过用户关联)
多态关联morphMany / morphTomorphTo文章和视频上的评论
多态多对多morphToManymorphedByMany文章和视频上的标签
查询范围
// Local scope — reusable query constraint
public function scopeActive(Builder $query): Builder
{
    return $query->where('status', 'active');
}

// Usage: User::active()->where('role', 'admin')->get();

// Global scope — applied to all queries on the model
protected static function booted(): void
{
    static::addGlobalScope('published', function (Builder $builder) {
        $builder->whereNotNull('published_at');
    });
}
访问器、修改器和类型转换
// Attribute accessor/mutator (Laravel 11+ syntax)
protected function fullName(): Attribute
{
    return Attribute::make(
        get: fn () => "{$this->first_name} {$this->last_name}",
    );
}

// Custom cast
protected function casts(): array
{
    return [
        'options'    => AsCollection::class,
        'address'    => AddressCast::class,
        'status'     => OrderStatus::class,  // Backed enum
        'metadata'   => 'array',
        'is_active'  => 'boolean',
        'amount'     => MoneyCast::class,
    ];
}
使用预加载优化查询
// BAD — N+1 problem: 1 query for posts + N queries for authors
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->author->name;  // Triggers lazy load each iteration
}

// GOOD — Eager load: 2 queries total
$posts = Post::with('author')->get();

// Nested eager loading
$posts = Post::with(['author', 'comments.user'])->get();

// Constrained eager loading
$posts = Post::with(['comments' => function ($query) {
    $query->where('approved', true)->latest()->limit(5);
}])->get();

// Prevent lazy loading in development
Model::preventLazyLoading(! app()->isProduction());

Blade 模板和 Livewire 组件

Blade 约定
  • 布局:使用 resources/views/layouts/app.blade.php 中的 @yield / @section,或基于组件的 <x-app-layout>
  • 组件:resources/views/components/ — 匿名组件或基于类的组件
  • 局部视图:使用 @include('partials.sidebar') 引入可复用片段
  • 使用 {{ }} 输出转义内容,仅在明确信任 HTML 时使用 {!! !!}
  • 优先使用 Blade 指令(@auth、@can、@env),而非原生 PHP 条件语句
Livewire 模式
// Full-page Livewire component (Livewire 3+)
#[Layout('layouts.app')]
#[Title('Dashboard')]
class Dashboard extends Component
{
    public string $search = '';

    #[Computed]
    public function users(): LengthAwarePaginator
    {
        return User::where('name', 'like', "%{$this->search}%")->paginate(15);
    }

    public function render(): View
    {
        return view('livewire.dashboard');
    }
}
前端技术栈决策表
决策选择 Livewire选择 Inertia
现有 Blade 代码库是否
需要类似 SPA 的体验部分支持(使用 wire:navigate)是
团队熟悉 Vue/React否是
优先考虑服务端渲染是取决于适配器
实时响应式交互是(轮询、流)需要配置 Echo
SEO 至关重要的页面两者均可两者均可(SSR 适配器)

队列、任务和事件模式

任务设计
class ProcessInvoice implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 3;
    public int $backoff = 60;
    public int $timeout = 120;
    public string $queue = 'invoices';

    public function __construct(public readonly Invoice $invoice) {}

    public function handle(PdfGenerator $generator): void
    {
        $generator->generate($this->invoice);
    }

    public function failed(Throwable $exception): void
    {
        // Notify admin, log to error tracker
    }
}
事件 / 监听器模式
// Dispatch event
OrderPlaced::dispatch($order);

// Listener (queued)
class SendOrderConfirmation implements ShouldQueue
{
    public function handle(OrderPlaced $event): void
    {
        Mail::to($event->order->user)->send(new OrderConfirmationMail($event->order));
    }
}
同步与异步决策表
任务加入队列同步
发送邮件 / 通知是绝不在请求周期内执行
生成 PDF是仅当耗时少于 2 秒且用户等待时
支付处理视情况而定 — 优先采用 Webhook 驱动网关响应时间少于 5 秒时
预热缓存是绝不
审计日志记录是(高频)或同步(低频)需要保证送达时
搜索索引是绝不

中间件和服务提供程序

中间件堆栈顺序

中间件顺序很重要。bootstrap/app.php 中的默认堆栈(Laravel 11+):

->withMiddleware(function (Middleware $middleware) {
    $middleware->web(append: [
        HandleInertiaRequests::class,  // After session, before response
    ]);

    $middleware->api(prepend: [
        EnsureFrontendRequestsAreStateful::class,  // Sanctum SPA auth
    ]);

    $middleware->alias([
        'role'     => EnsureUserHasRole::class,
        'verified' => EnsureEmailIsVerified::class,
    ]);
})
服务提供程序最佳实践
  • 在 register() 中注册绑定,绝不要在其中从容器解析依赖
  • 启动逻辑(事件监听器、路由模型绑定、宏)放在 boot() 中
  • 对并非每个请求都需要的绑定,使用延迟加载的提供程序
  • 避免在提供程序中执行繁重逻辑 — 委托给专用类

使用 Pest 进行测试

单元测试
test('order total calculates tax correctly', function () {
    $order = Order::factory()->make(['subtotal' => 10000, 'tax_rate' => 0.08]);

    expect($order->total)->toBe(10800);
});
功能测试
test('authenticated user can create a post', function () {
    $user = User::factory()->create();

    $response = $this->actingAs($user)
        ->postJson('/api/posts', [
            'title' => 'My Post',
            'body'  => 'Content here.',
        ]);

    $response->assertCreated()
        ->assertJsonPath('data.title', 'My Post');

    $this->assertDatabaseHas('posts', [
        'user_id' => $user->id,
        'title'   => 'My Post',
    ]);
});
队列和事件伪造
test('placing an order dispatches confirmation job', function () {
    Queue::fake();

    $order = Order::factory()->create();
    PlaceOrder::dispatch($order);

    Queue::assertPushed(SendOrderConfirmation::class, function ($job) use ($order) {
        return $job->order->id === $order->id;
    });
});
浏览器测试(Dusk)
test('user can complete checkout flow', function () {
    $this->browse(function (Browser $browser) {
        $browser->loginAs(User::factory()->create())
            ->visit('/cart')
            ->press('Checkout')
            ->waitForText('Order Confirmed')
            ->assertSee('Thank you');
    });
});

Artisan 命令、迁移、填充器和工厂

迁移约定
// Always include down() for rollback capability
public function up(): void
{
    Schema::create('invoices', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->constrained()->cascadeOnDelete();
        $table->string('number')->unique();
        $table->integer('amount');          // Store money as cents
        $table->string('currency', 3);
        $table->string('status')->default('draft');
        $table->timestamp('due_at')->nullable();
        $table->timestamps();
        $table->softDeletes();

        $table->index(['user_id', 'status']);
    });
}
工厂模式
class InvoiceFactory extends Factory
{
    public function definition(): array
    {
        return [
            'user_id'  => User::factory(),
            'number'   => $this->faker->unique()->numerify('INV-####'),
            'amount'   => $this->faker->numberBetween(1000, 100000),
            'currency' => 'USD',
            'status'   => 'draft',
            'due_at'   => now()->addDays(30),
        ];
    }

    public function paid(): static
    {
        return $this->state(fn () => ['status' => 'paid']);
    }

    public function overdue(): static
    {
        return $this->state(fn () => [
            'status' => 'sent',
            'due_at' => now()->subDays(7),
        ]);
    }
}

Laravel 目录结构约定

app/
├── Actions/              # Single-purpose action classes
├── Casts/                # Custom Eloquent casts
├── Console/Commands/     # Artisan commands
├── Enums/                # PHP backed enums
├── Events/               # Event classes
├── Exceptions/           # Custom exception classes
├── Http/
│   ├── Controllers/      # Resourceful or single-action controllers
│   ├── Middleware/        # Request/response middleware
│   └── Requests/         # Form Request validation
├── Jobs/                 # Queued job classes
├── Listeners/            # Event listener classes
├── Mail/                 # Mailable classes
├── Models/               # Eloquent models
├── Notifications/        # Notification classes
├── Observers/            # Model observers
├── Policies/             # Authorization policies
├── Providers/            # Service providers
├── Rules/                # Custom validation rules
├── Services/             # Domain service classes
└── View/Components/      # Blade view components
database/
├── factories/            # Model factories
├── migrations/           # Schema migrations (timestamped)
└── seeders/              # Database seeders
resources/views/
├── components/           # Blade components
├── layouts/              # Layout templates
├── livewire/             # Livewire component views
└── mail/                 # Email templates
routes/
├── api.php               # API routes
├── channels.php          # Broadcast channels
├── console.php           # Artisan closures
└── web.php               # Web routes
tests/
├── Feature/              # Feature (integration) tests
├── Unit/                 # Unit tests
└── Browser/              # Dusk browser tests

决策表

身份验证策略
场景推荐方案
SPA + 同域Sanctum(基于 Cookie,CSRF)
SPA + 不同域Sanctum(基于令牌)
移动应用Sanctum(基于令牌)
第三方 API 使用者Passport(OAuth2)
简单 API 令牌Sanctum(明文哈希)
社交登录Socialite + Sanctum
缓存层
数据类型缓存驱动TTL失效方式
配置 / 路由 / 视图File(artisan cache)直到下次部署artisan optimize:clear
数据库查询结果Redis / Memcached5-60 分钟事件驱动或 TTL
整页 / 片段Redis1-15 分钟缓存标签
会话数据Redis会话生命周期自动
速率限制Redis窗口时长自动
文件存储
场景磁盘驱动
用户上传(生产环境)s3Amazon S3 / 兼容服务
用户上传(本地开发)local本地文件系统
公共资源public本地存储并使用符号链接
临时文件local本地存储,按计划清理

反模式 / 常见错误

反模式失败原因应采取的做法
控制器过于臃肿业务逻辑难以测试和维护将逻辑移至 Action 或 Service 类
在控制器中直接编写 SQL有 SQL 注入风险,且不具备可移植性使用 Eloquent 或 Query Builder
缺少批量赋值保护存在数据篡改漏洞始终定义 $fillable 或 $guarded
在控制器中内联验证将验证与 HTTP 层耦合使用 Form Requests
Job 未配置重试 / 退避失败无提示,且无法恢复配置 $tries、$backoff、failed()
过度使用全局作用域隐藏的查询行为会令开发者措手不及优先使用局部作用域
将金额存为浮点数会出现浮点精度误差使用整数表示分,在展示时转换
缺少数据库索引数据量增大时查询缓慢为 WHERE + ORDER BY 添加复合索引
在配置文件中存放密钥凭据可能泄露到版本控制中仅使用 .env
使用生产数据库进行测试数据可能损坏,测试结果不可靠使用内存中的 SQLite 或专用测试数据库
在 API 响应中使用延迟加载产生 N+1 查询,导致 API 响应缓慢在开发环境中启用 preventLazyLoading()

防止自我合理化

  • 不要跳过迁移并直接修改数据库——迁移才是事实来源。
  • 不要因为“这样更快”就把业务逻辑放进控制器——请使用 Action 类。
  • 不要因为“验证很简单”就跳过 Form Requests——验证逻辑总会不断增长。
  • 不要因为“很烦人”就禁用 preventLazyLoading()——请修复 N+1 查询。
  • 不要因为“金额很小”就将金额存为浮点数——精度误差会不断累积。

集成点

技能关联方式
php-specialist现代 PHP 8.x 模式是所有 Laravel 代码的基础
laravel-boostAI 辅助开发指南和 MCP 工具
senior-backendAPI 设计、缓存策略、事件驱动架构
test-driven-development使用 RED-GREEN-REFACTOR 的 Pest 测试工作流
database-schema-design迁移规划、索引策略、数据建模
security-reviewSanctum/Passport 配置、CSRF、输入验证
performance-optimization查询分析、缓存调优、队列 Worker 扩缩容
deploymentForge/Vapor/Envoyer 部署、artisan optimize
context7 MCP信息不确定时,获取最新的 Laravel 文档
laravel/docs GitHubLaravel API 参考的权威来源

技能类型

灵活——根据工作范围调整多阶段流程。单个模型变更可以完全跳过 Phase 2,而新模块则应遵循全部五个阶段。无论工作范围如何,核心规范(预加载、Form Requests、Pest 测试、优先迁移的架构变更)都不可妥协。

评论

支持 Markdown