Laravel模式

Mattakushi4322026-10-25查看 844复制 1933

何时激活:Laravel、Eloquent ORM、服务容器、中间件、表单请求、资源控制器、artisan、队列、事件和侦听器、服务提供者、策略

Download (.md)

📘如何使用这个技能

  1. 1
    复制技能内容·点击上方「Copy SKILL.md」复制全部内容,或 Download 下载到本地
  2. 2
    打开你的 AI 客户端·支持 Claude Code、Trae、Cursor、ChatGPT、DeepSeek、Kimi 等任意 AI 助手
  3. 3
    粘贴为系统提示/知识文件·Claude Code:放入 .claude/skills/ 目录;普通对话:作为首条消息发送并说「请严格按这份技能文档执行」
  4. 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`
来源:skillsdirectory

评论0

登录后参与评论

还没有评论,来抢沙发吧