Laravel模式
Mattakushi4322026-10-25查看 844复制 1933
何时激活:Laravel、Eloquent ORM、服务容器、中间件、表单请求、资源控制器、artisan、队列、事件和侦听器、服务提供者、策略
📘如何使用这个技能
- 1复制技能内容·点击上方「Copy SKILL.md」复制全部内容,或 Download 下载到本地
- 2打开你的 AI 客户端·支持 Claude Code、Trae、Cursor、ChatGPT、DeepSeek、Kimi 等任意 AI 助手
- 3粘贴为系统提示/知识文件·Claude Code:放入 .claude/skills/ 目录;普通对话:作为首条消息发送并说「请严格按这份技能文档执行」
- 4直接提出你的需求·AI 会按技能定义的工作流、格式和约束来处理,无需再解释背景
💡 提示:技能生效后,每次对话只需一句需求,AI 会按 SKILL.md 的流程执行。
SKILL.md5147 chars
---
name: laravel-patterns
description: "When to activate: Laravel, Eloquent ORM, service container, middleware, form requests, resource controllers, artisan, queues, events and listeners, service providers, policies"
origin: zakr
metadata:
namespace: zakr/devtools-pack
version: 1.0.0
category: engineering
language: php
platforms: [claude-code, codex, gemini-cli, cursor, aider, windsurf]
---
# Laravel Patterns
## When to Use
Building or reviewing a Laravel application: controllers, Eloquent models, form requests, service providers, jobs, or authorization policies.
## Core Patterns
### Thin Controllers, Form Requests for Validation
```php
final class StoreOrderRequest extends FormRequest
{
public function authorize(): bool
{
return $this->user()->can('create', Order::class);
}
public function rules(): array
{
return [
'customer_id' => ['required', 'exists:customers,id'],
'items' => ['required', 'array', 'min:1'],
'items.*.sku' => ['required', 'string', 'exists:products,sku'],
];
}
}
final class OrderController extends Controller
{
public function __construct(private readonly CreateOrder $createOrder)
{
}
public function store(StoreOrderRequest $request): JsonResponse
{
$order = $this->createOrder->handle($request->validated());
return OrderResource::make($order)->response()->setStatusCode(201);
}
}
```
### Service/Action Classes Over Fat Models
Push business logic out of controllers and models into single-purpose action classes.
```php
final class CreateOrder
{
public function __construct(
private readonly OrderRepository $orders,
private readonly InventoryService $inventory,
) {
}
public function handle(array $data): Order
{
return DB::transaction(function () use ($data) {
$this->inventory->reserve($data['items']);
return $this->orders->create($data);
});
}
}
```
### Eloquent: Avoid N+1 with Eager Loading
```php
// BAD: N+1 query — one query per order for its customer
$orders = Order::all();
foreach ($orders as $order) {
echo $order->customer->name;
}
// GOOD: eager load the relation
$orders = Order::with('customer', 'items.product')->get();
// Enforce it in local development
Model::preventLazyLoading(! app()->isProduction());
```
### Query Scopes Instead of Repeated where()
```php
final class Order extends Model
{
public function scopePending(Builder $query): Builder
{
return $query->where('status', OrderStatus::Pending);
}
public function scopeForCustomer(Builder $query, Customer $customer): Builder
{
return $query->where('customer_id', $customer->id);
}
}
Order::pending()->forCustomer($customer)->get();
```
### Policies for Authorization
```php
final class OrderPolicy
{
public function view(User $user, Order $order): bool
{
return $user->id === $order->customer_id || $user->isAdmin();
}
}
// In a controller or Blade template
$this->authorize('view', $order);
@can('view', $order) ... @endcan
```
### Events and Listeners for Side Effects
```php
final class OrderShipped
{
public function __construct(public readonly Order $order)
{
}
}
final class SendShippingNotification
{
public function handle(OrderShipped $event): void
{
Mail::to($event->order->customer)->send(new OrderShippedMail($event->order));
}
}
event(new OrderShipped($order));
```
## Checklist
- [ ] Validation lives in `FormRequest` classes, not inline in controllers
- [ ] Business logic in action/service classes, not in controllers or models
- [ ] `Model::preventLazyLoading()` enabled outside production
- [ ] Authorization goes through Policies/Gates, not manual `if ($user->id === ...)` checks scattered in controllers
- [ ] Queries use scopes for reused filters
- [ ] Mass-assignment protected via `$fillable` (never `$guarded = []`)
- [ ] Migrations are reversible (`down()` implemented)
## Anti-Patterns
```php
// BAD: raw SQL fragments with interpolated variables
DB::select("SELECT * FROM orders WHERE status = '$status'");
// GOOD: query builder / Eloquent, parameter binding
Order::where('status', $status)->get();
```
```php
// BAD: business logic and cross-cutting concerns in the model
class Order extends Model {
public function ship() {
$this->update(['status' => 'shipped']);
Mail::to($this->customer)->send(new OrderShippedMail($this));
Log::info('order shipped');
}
}
// GOOD: model stays a thin persistence layer; orchestration in an action class
```
## Quick Reference
| Concern | Laravel Tool |
|---|---|
| Input validation | `FormRequest` |
| Authorization | `Policy` / `Gate` |
| Cross-cutting side effects | Events + Listeners |
| Background work | Queued Jobs |
| Reused query filters | Local Scopes |
| API shape | `JsonResource` |
| Config-driven wiring | `ServiceProvider` |
## See Also
- `skills/php-ecosystem/php-patterns.md`
- `skills/php-ecosystem/php-database.md`
- `skills/php-ecosystem/php-testing.md`