laravel-specialist
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseLaravel Specialist
Laravel 专家指南
Overview
概述
Design, build, and maintain production-grade Laravel applications following the framework's conventions and best practices. This skill covers the full Laravel ecosystem: Eloquent ORM with advanced relationship patterns, Blade templating and Livewire interactivity, queue and event systems, middleware pipelines, service providers, Pest testing at every layer, and Artisan tooling for migrations, seeders, and factories.
Apply this skill whenever Laravel is the application framework, whether greenfield or brownfield.
遵循框架约定和最佳实践,设计、构建并维护生产级Laravel应用。本技能覆盖完整的Laravel生态:支持高级关系模式的Eloquent ORM、Blade模板与Livewire交互能力、队列与事件系统、中间件管道、服务提供者、全层级Pest测试,以及用于迁移、数据填充、工厂类的Artisan工具。
无论新项目还是存量项目,只要使用Laravel作为应用框架都可应用本技能。
Multi-Phase Process
多阶段流程
Phase 1: Context Discovery
阶段1:上下文梳理
- Identify Laravel version (->
composer.json)laravel/framework - Scan for enabled packages and custom configuration
config/ - Map existing models, relationships, and migration history
- Review for API, web, console, and channel definitions
routes/ - Catalog installed first-party packages (Sanctum, Horizon, Telescope, Pulse, Pennant, Scout, Cashier)
- Check for Livewire, Inertia, or Blade-only frontend stack
STOP — Do NOT begin architecture review without knowing the Laravel version and installed packages.
- 确认Laravel版本(->
composer.json)laravel/framework - 扫描目录查看已启用的包和自定义配置
config/ - 梳理现有模型、关联关系和迁移历史
- 查看目录下的API、Web、控制台和广播通道定义
routes/ - 统计已安装的官方包(Sanctum、Horizon、Telescope、Pulse、Pennant、Scout、Cashier)
- 确认前端技术栈是Livewire、Inertia还是仅用Blade
注意 — 未明确Laravel版本和已安装包之前,请勿开始架构评审。
Documentation Verification Protocol
文档校验规则
[HARD-GATE] When uncertain about any Laravel API — verify, don't guess. Use then (preferred). Fallback: fetch from . For Livewire, Pest, Inertia — resolve each via context7 separately. Returned docs override memorized knowledge.
mcp__context7__resolve-library-idmcp__context7__query-docshttps://github.com/laravel/docs[强制校验] 当对任意Laravel API存在疑问时,一定要校验不要猜测。优先使用然后调用查询文档,备选方案是从获取文档。对于Livewire、Pest、Inertia,需要分别通过context7查询。返回的文档优先级高于记忆中的知识。
mcp__context7__resolve-library-idmcp__context7__query-docshttps://github.com/laravel/docsPhase 2: Architecture Review
阶段2:架构评审
- Verify directory structure follows Laravel conventions (see section below)
- Assess service provider registrations and deferred loading
- Review middleware stack ordering and grouping
- Evaluate queue connection configuration and worker topology
- Check caching strategy (config, route, view, application-level)
STOP — Do NOT begin implementation until architecture gaps are documented.
- 确认目录结构符合Laravel约定(参考后续章节)
- 评估服务提供者注册和延迟加载逻辑
- 检查中间件栈的顺序和分组配置
- 评估队列连接配置和worker拓扑结构
- 检查缓存策略(配置、路由、视图、应用级缓存)
注意 — 架构差距未记录完成前,请勿开始开发实现。
Phase 3: Implementation
阶段3:开发实现
- Write migrations first — schema is the source of truth
- Build Eloquent models with relationships, scopes, casts, and accessors
- Implement business logic in dedicated Action or Service classes
- Create controllers (single-action or resourceful) bound to routes
- Add Form Requests for validation, Policies for authorization
- Wire events, listeners, and jobs for asynchronous workflows
STOP — Do NOT skip Form Requests and Policies. Inline validation and authorization are anti-patterns.
- 优先编写迁移文件:数据库 schema 是唯一数据基准
- 构建Eloquent模型,包含关联关系、查询作用域、类型转换和访问器
- 在专门的Action或Service类中实现业务逻辑
- 创建绑定到路由的控制器(单动作或资源型控制器)
- 新增表单请求做验证,策略类做权限控制
- 关联事件、监听器和任务实现异步工作流
注意 — 请勿跳过表单请求和策略类编写,内联验证和权限控制是反模式。
Phase 4: Testing
阶段4:测试
- Unit tests for isolated logic (Actions, Value Objects, Casts)
- Feature tests for HTTP endpoints and middleware behavior
- Browser tests with Laravel Dusk for critical user flows
- Database assertions with ,
assertDatabaseHasassertSoftDeleted - Queue and event fakes for side-effect verification
STOP — Do NOT proceed to optimization without passing tests at all layers.
- 为隔离逻辑编写单元测试(Action、值对象、类型转换)
- 为HTTP接口和中间件行为编写功能测试
- 用Laravel Dusk为核心用户流程编写浏览器测试
- 使用、
assertDatabaseHas做数据库断言assertSoftDeleted - 使用队列和事件伪造验证副作用逻辑
注意 — 所有层级测试未通过前,请勿进入优化阶段。
Phase 5: Optimization
阶段5:性能优化
- Apply eager loading to eliminate N+1 queries
- Cache expensive computations and config/route/view
- Index frequently-queried columns; use to verify
EXPLAIN - Profile with Telescope or Debugbar in development
- Configure Horizon for production queue monitoring
- 应用预加载消除N+1查询问题
- 缓存耗时计算结果、配置/路由/视图编译结果
- 为高频查询字段加索引,使用校验索引生效情况
EXPLAIN - 开发环境用Telescope或Debugbar做性能分析
- 生产环境配置Horizon做队列监控
Eloquent Patterns
Eloquent 设计模式
Relationships
关联关系
| Relationship | Method | Inverse | Use Case |
|---|---|---|---|
| One-to-One | | | User -> Profile |
| One-to-Many | | | Post -> Comments |
| Many-to-Many | | | User <-> Roles (pivot) |
| Has-Many-Through | | — | Country -> Posts (through Users) |
| Polymorphic | | | Comments on Posts and Videos |
| Many-to-Many Polymorphic | | | Tags on Posts and Videos |
| 关系类型 | 方法名 | 反向关联 | 适用场景 |
|---|---|---|---|
| 一对一 | | | 用户 -> 用户资料 |
| 一对多 | | | 文章 -> 评论 |
| 多对多 | | | 用户 <-> 角色(中间表) |
| 远程一对多 | | — | 国家 -> 文章(通过用户关联) |
| 多态关联 | | | 同时关联文章和视频的评论 |
| 多态多对多 | | | 同时关联文章和视频的标签 |
Scopes
查询作用域
php
// 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');
});
}php
// 本地作用域 — 可复用的查询约束
public function scopeActive(Builder $query): Builder
{
return $query->where('status', 'active');
}
// 用法: User::active()->where('role', 'admin')->get();
// 全局作用域 — 模型的所有查询都会自动应用
protected static function booted(): void
{
static::addGlobalScope('published', function (Builder $builder) {
$builder->whereNotNull('published_at');
});
}Accessors, Mutators, and Casts
访问器、修改器和类型转换
php
// 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,
];
}php
// 属性访问器/修改器(Laravel 11+ 语法)
protected function fullName(): Attribute
{
return Attribute::make(
get: fn () => "{$this->first_name} {$this->last_name}",
);
}
// 自定义类型转换
protected function casts(): array
{
return [
'options' => AsCollection::class,
'address' => AddressCast::class,
'status' => OrderStatus::class, // 枚举类型
'metadata' => 'array',
'is_active' => 'boolean',
'amount' => MoneyCast::class,
];
}Query Optimization with Eager Loading
预加载查询优化
php
// 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());php
// 反面案例 — N+1问题:1次查询查文章 + N次查询查作者
$posts = Post::all();
foreach ($posts as $post) {
echo $post->author->name; // 每次循环都会触发懒加载
}
// 正确写法 — 预加载:总共仅2次查询
$posts = Post::with('author')->get();
// 嵌套预加载
$posts = Post::with(['author', 'comments.user'])->get();
// 带条件的预加载
$posts = Post::with(['comments' => function ($query) {
$query->where('approved', true)->latest()->limit(5);
}])->get();
// 开发环境禁用懒加载
Model::preventLazyLoading(! app()->isProduction());Blade Templates and Livewire Components
Blade 模板与 Livewire 组件
Blade Conventions
Blade 开发约定
- Layouts: using
resources/views/layouts/app.blade.php/@yieldor component-based@section<x-app-layout> - Components: — anonymous or class-based
resources/views/components/ - Partials: for reusable fragments
@include('partials.sidebar') - Use for escaped output,
{{ }}only when HTML is explicitly trusted{!! !!} - Prefer Blade directives (,
@auth,@can) over raw PHP conditionals@env
- 布局文件:可使用
resources/views/layouts/app.blade.php/@yield或组件式写法@section<x-app-layout> - 组件文件:存放在,支持匿名组件或类组件
resources/views/components/ - 局部模板:使用引入可复用片段
@include('partials.sidebar') - 输出内容使用做自动转义,仅当明确信任HTML内容时才使用
{{ }}{!! !!} - 优先使用Blade指令(、
@auth、@can)而非原生PHP条件语句@env
Livewire Patterns
Livewire 设计模式
php
// 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');
}
}php
// 全页面Livewire组件(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');
}
}Frontend Stack Decision Table
前端技术栈选型表
| Decision | Choose Livewire | Choose Inertia |
|---|---|---|
| Existing Blade codebase | Yes | No |
| SPA-like experience required | Partial (with wire:navigate) | Yes |
| Team has Vue/React expertise | No | Yes |
| Server-side rendering priority | Yes | Depends on adapter |
| Real-time reactivity | Yes (polling, streams) | Requires Echo setup |
| SEO-critical pages | Either works | Either works (SSR adapter) |
| 选型维度 | 选择Livewire | 选择Inertia |
|---|---|---|
| 现有Blade代码栈 | 是 | 否 |
| 需要类SPA的交互体验 | 部分支持(配合wire:navigate) | 是 |
| 团队具备Vue/React开发能力 | 否 | 是 |
| 服务端渲染优先级高 | 是 | 取决于适配器 |
| 需要实时响应能力 | 是(轮询、流式推送) | 需要额外配置Echo |
| SEO高优先级页面 | 两者均可 | 两者均可(使用SSR适配器) |
Queue, Job, and Event Patterns
队列、任务和事件模式
Job Design
任务设计规范
php
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
}
}php
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
{
// 通知管理员,上报到错误追踪系统
}
}Event / Listener Pattern
事件/监听器模式
php
// 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));
}
}php
// 触发事件
OrderPlaced::dispatch($order);
// 异步监听器
class SendOrderConfirmation implements ShouldQueue
{
public function handle(OrderPlaced $event): void
{
Mail::to($event->order->user)->send(new OrderConfirmationMail($event->order));
}
}Sync vs Async Decision Table
同步/异步选型表
| Task | Queued | Synchronous |
|---|---|---|
| Sending emails / notifications | Yes | Never in request cycle |
| PDF generation | Yes | Only if < 2s and user waits |
| Payment processing | Depends — webhook-driven preferred | If gateway responds < 5s |
| Cache warming | Yes | Never |
| Audit logging | Yes (high-volume) or Sync (low-volume) | If guaranteed delivery needed |
| Search indexing | Yes | Never |
| 任务类型 | 异步队列 | 同步执行 |
|---|---|---|
| 发送邮件/通知 | 是 | 禁止在请求周期内同步执行 |
| PDF生成 | 是 | 仅当生成耗时<2s且用户需要等待时使用 |
| 支付处理 | 优先使用webhook驱动的异步方案 | 仅当网关响应<5s时可同步 |
| 缓存预热 | 是 | 禁止同步执行 |
| 审计日志 | 高并发场景用异步,低并发场景可同步 | 需要保证投递可靠性时用同步 |
| 搜索索引更新 | 是 | 禁止同步执行 |
Middleware and Service Providers
中间件与服务提供者
Middleware Stack Ordering
中间件栈顺序配置
Middleware order matters. The default stack in (Laravel 11+):
bootstrap/app.phpphp
->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,
]);
})中间件顺序会影响执行逻辑,Laravel 11+的默认栈配置在中:
bootstrap/app.phpphp
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [
HandleInertiaRequests::class, // 会话之后,响应生成之前执行
]);
$middleware->api(prepend: [
EnsureFrontendRequestsAreStateful::class, // Sanctum SPA 认证
]);
$middleware->alias([
'role' => EnsureUserHasRole::class,
'verified' => EnsureEmailIsVerified::class,
]);
})Service Provider Best Practices
服务提供者最佳实践
- Register bindings in , never resolve from the container there
register() - Boot logic (event listeners, route model binding, macros) goes in
boot() - Use deferred providers for bindings that are not needed on every request
- Avoid heavy logic in providers — delegate to dedicated classes
- 绑定逻辑放在方法中,不要在此方法中从容器解析实例
register() - 启动逻辑(事件监听器、路由模型绑定、宏定义)放在方法中
boot() - 非每次请求都需要的绑定使用延迟服务提供者
- 避免在服务提供者中编写复杂逻辑,委托给专门的类实现
Testing with Pest
使用Pest进行测试
Unit Test
单元测试
php
test('order total calculates tax correctly', function () {
$order = Order::factory()->make(['subtotal' => 10000, 'tax_rate' => 0.08]);
expect($order->total)->toBe(10800);
});php
test('order total calculates tax correctly', function () {
$order = Order::factory()->make(['subtotal' => 10000, 'tax_rate' => 0.08]);
expect($order->total)->toBe(10800);
});Feature Test
功能测试
php
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',
]);
});php
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',
]);
});Queue and Event Fakes
队列与事件伪造测试
php
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;
});
});php
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;
});
});Browser Test (Dusk)
浏览器测试(Dusk)
php
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');
});
});php
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 Commands, Migrations, Seeders, Factories
Artisan命令、迁移、数据填充、工厂类
Migration Conventions
迁移开发约定
php
// 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']);
});
}php
// 必须编写down()方法支持回滚
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'); // 金额以分为单位存储
$table->string('currency', 3);
$table->string('status')->default('draft');
$table->timestamp('due_at')->nullable();
$table->timestamps();
$table->softDeletes();
$table->index(['user_id', 'status']);
});
}Factory Patterns
工厂类设计模式
php
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),
]);
}
}php
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 Directory Structure Conventions
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 testsapp/
├── Actions/ # 单用途Action类
├── Casts/ # 自定义Eloquent类型转换类
├── Console/Commands/ # Artisan命令类
├── Enums/ # PHP枚举类
├── Events/ # 事件类
├── Exceptions/ # 自定义异常类
├── Http/
│ ├── Controllers/ # 资源型或单动作控制器
│ ├── Middleware/ # 请求/响应中间件
│ └── Requests/ # 表单请求验证类
├── Jobs/ # 队列任务类
├── Listeners/ # 事件监听器类
├── Mail/ # 邮件类
├── Models/ # Eloquent模型类
├── Notifications/ # 通知类
├── Observers/ # 模型观察者类
├── Policies/ # 授权策略类
├── Providers/ # 服务提供者类
├── Rules/ # 自定义验证规则类
├── Services/ # 领域服务类
└── View/Components/ # Blade视图组件类
database/
├── factories/ # 模型工厂类
├── migrations/ # 带时间戳的schema迁移文件
└── seeders/ # 数据库填充类
resources/views/
├── components/ # Blade组件
├── layouts/ # 布局模板
├── livewire/ # Livewire组件视图
└── mail/ # 邮件模板
routes/
├── api.php # API路由
├── channels.php # 广播通道
├── console.php # Artisan闭包命令
└── web.php # Web路由
tests/
├── Feature/ # 功能(集成)测试
├── Unit/ # 单元测试
└── Browser/ # Dusk浏览器测试Decision Tables
选型表
Authentication Strategy
认证方案选型
| Scenario | Recommended Approach |
|---|---|
| SPA + same domain | Sanctum (cookie-based, CSRF) |
| SPA + different domain | Sanctum (token-based) |
| Mobile app | Sanctum (token-based) |
| Third-party API consumers | Passport (OAuth2) |
| Simple API tokens | Sanctum (plaintext hash) |
| Social login | Socialite + Sanctum |
| 场景 | 推荐方案 |
|---|---|
| 同域SPA | Sanctum(基于Cookie,CSRF防护) |
| 跨域SPA | Sanctum(基于Token) |
| 移动端应用 | Sanctum(基于Token) |
| 第三方API消费者 | Passport(OAuth2) |
| 简单API令牌验证 | Sanctum(明文哈希) |
| 社交登录 | Socialite + Sanctum |
Caching Layer
缓存层选型
| Data Type | Cache Driver | TTL | Invalidation |
|---|---|---|---|
| Config / routes / views | File (artisan cache) | Until next deploy | |
| Database query results | Redis / Memcached | 5-60 min | Event-driven or TTL |
| Full-page / fragment | Redis | 1-15 min | Cache tags |
| Session data | Redis | Session lifetime | Automatic |
| Rate limiting | Redis | Window duration | Automatic |
| 数据类型 | 缓存驱动 | 过期时间 | 失效策略 |
|---|---|---|---|
| 配置/路由/视图编译 | 文件(artisan cache) | 到下次部署前 | |
| 数据库查询结果 | Redis / Memcached | 5-60分钟 | 事件驱动或自动过期 |
| 整页/页面片段缓存 | Redis | 1-15分钟 | 缓存标签 |
| 会话数据 | Redis | 会话生命周期 | 自动失效 |
| 限流数据 | Redis | 限流窗口时长 | 自动失效 |
File Storage
文件存储选型
| Scenario | Disk | Driver |
|---|---|---|
| User uploads (production) | | Amazon S3 / compatible |
| User uploads (local dev) | | Local filesystem |
| Public assets | | Local with symlink |
| Temporary files | | Local, pruned by schedule |
| 场景 | 磁盘名 | 驱动 |
|---|---|---|
| 生产环境用户上传 | | Amazon S3 / 兼容S3的存储服务 |
| 本地开发用户上传 | | 本地文件系统 |
| 公开静态资源 | | 带软链的本地存储 |
| 临时文件 | | 本地存储,通过定时任务清理 |
Anti-Patterns / Common Mistakes
反模式/常见错误
| Anti-Pattern | Why It Fails | What To Do Instead |
|---|---|---|
| Fat controllers | Untestable, unmaintainable business logic | Move logic to Action or Service classes |
| Raw SQL in controllers | SQL injection risk, not portable | Use Eloquent or Query Builder |
| Missing mass-assignment protection | Data manipulation vulnerabilities | Always define |
| Inline validation in controllers | Couples validation to HTTP layer | Use Form Requests |
| Jobs without retry/backoff config | Silent failures, no recovery | Configure |
| Over-using global scopes | Hidden query behavior surprises developers | Prefer local scopes |
| Storing money as floats | Floating-point precision errors | Use integer cents, convert at presentation |
| Missing database indexes | Slow queries at scale | Add composite indexes for WHERE + ORDER BY |
| Secrets in config files | Credential leaks in version control | Use |
| Testing against production DB | Data corruption, unreliable tests | Use SQLite in-memory or dedicated test DB |
| Lazy loading in API responses | N+1 queries, slow API responses | Enable |
| 反模式 | 问题所在 | 正确做法 |
|---|---|---|
| 胖控制器 | 业务逻辑不可测试、难以维护 | 将逻辑迁移到Action或Service类 |
| 控制器中写原生SQL | 存在SQL注入风险,兼容性差 | 使用Eloquent或查询构造器 |
| 缺失批量赋值保护 | 存在数据篡改漏洞 | 始终定义 |
| 控制器中内联验证 | 验证逻辑与HTTP层耦合 | 使用表单请求验证 |
| 任务未配置重试/退避策略 | 静默失败,无恢复能力 | 配置 |
| 过度使用全局作用域 | 隐藏查询逻辑,给开发带来意料之外的问题 | 优先使用本地作用域 |
| 金额用浮点数存储 | 存在浮点精度误差 | 用整数存储单位为分的金额,展示层再转换 |
| 缺失数据库索引 | 规模扩大后查询变慢 | 为WHERE和ORDER BY的组合字段添加联合索引 |
| 配置文件中写密钥 | 版本控制泄露凭证 | 仅通过 |
| 针对生产库进行测试 | 数据损坏,测试结果不可靠 | 使用SQLite内存库或专用测试库 |
| API响应中使用懒加载 | 出现N+1查询,API响应变慢 | 开发环境开启 |
Anti-Rationalization Guards
禁止规避规则
- Do NOT skip migrations and edit the database directly -- migrations are the source of truth.
- Do NOT put business logic in controllers because "it's faster" -- use Action classes.
- Do NOT skip Form Requests because "the validation is simple" -- it always grows.
- Do NOT disable because "it's annoying" -- fix the N+1 queries.
preventLazyLoading() - Do NOT store money as floats because "the amounts are small" -- precision errors compound.
- 请勿跳过迁移直接修改数据库 —— 迁移是唯一的schema基准
- 请勿为了「开发更快」把业务逻辑写在控制器中 —— 使用Action类
- 请勿因为「验证逻辑简单」跳过表单请求编写 —— 逻辑总会迭代变复杂
- 请勿因为「太麻烦」关闭—— 修复N+1查询问题
preventLazyLoading() - 请勿因为「金额很小」用浮点数存储金额 —— 精度误差会累积
Integration Points
关联技能
| Skill | How It Connects |
|---|---|
| Modern PHP 8.x patterns underpin all Laravel code |
| AI-assisted development guidelines and MCP tooling |
| API design, caching strategies, event-driven architecture |
| Pest testing workflow with RED-GREEN-REFACTOR |
| Migration planning, indexing strategy, data modeling |
| Sanctum/Passport configuration, CSRF, input validation |
| Query profiling, cache tuning, queue worker scaling |
| Forge/Vapor/Envoyer deployment, |
| Fetches up-to-date Laravel docs when information is uncertain |
| Authoritative source for Laravel API reference |
| 技能 | 关联关系 |
|---|---|
| 现代PHP 8.x语法是所有Laravel代码的基础 |
| AI辅助开发指南和MCP工具 |
| API设计、缓存策略、事件驱动架构 |
| 基于Pest的红-绿-重构测试工作流 |
| 迁移规划、索引策略、数据建模 |
| Sanctum/Passport配置、CSRF防护、输入验证 |
| 查询分析、缓存调优、队列worker扩容 |
| Forge/Vapor/Envoyer部署、 |
| 信息不确定时获取最新Laravel文档 |
| Laravel API参考的权威来源 |
Skill Type
技能类型
FLEXIBLE — Adapt the multi-phase process to the scope of work. A single model change may skip Phase 2 entirely, while a new module should follow all five phases. Core conventions (eager loading, Form Requests, Pest tests, migration-first schema changes) are non-negotiable regardless of scope.
灵活适配 —— 可根据工作范围调整多阶段流程。单个模型修改可以直接跳过阶段2,而新模块开发应该遵循完整的五个阶段。核心约定(预加载、表单请求、Pest测试、迁移优先的schema变更)无论项目规模大小都是必须遵守的。