Communitygithub.com

laravel-patterns

Laravel アーキテクチャパターン、ルーティング/コントローラー、Eloquent ORM、サービスレイヤー、キュー、イベント、キャッシング、API リソースを本番アプリ向けに提供します。Laravel アプリの構築やレビュー(コントローラー、Eloquent、サービスレイヤー、キュー、API リソース)の際に使用します。

laravel-patterns とは?

このスキルは、スケーラブルでメンテナンスしやすい Laravel アプリケーションを構築するためのプロダクショングレードのアーキテクチャパターンを提供します。コントローラーは薄く保ち、オーケストレーションはサービス、単一目的のロジックはアクションに委譲する「コントローラー -> サービス -> アクション」パターンを推奨し、ルーティングでは明示的なバインディングとスコープバインディングを活用して予測可能性を高め、アクセス制御を実施します。Eloquent モデルでは型付きモデル、カスタムキャスト、スコープを活用し、ドメインロジックの一貫性を維持します。また、I/O の重い処理はキューに、高コストな読み取りはキャッシュにオフロードし、設定は `config/*` に集中管理して環境を明示的にします。Laravel アプリケーションの設計、コードレビュー、リファクタリング時に特に役立ちます。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/laravel-patterns

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Laravel 開発パターン

スケーラブルでメンテナンスしやすいアプリケーションのための、プロダクショングレードの Laravel アーキテクチャパターン。

使用するタイミング

  • Laravel Web アプリケーションまたは API を構築する場合
  • コントローラー、サービス、ドメインロジックを構造化する場合
  • Eloquent モデルとリレーションシップを扱う場合
  • リソースとページネーションを使用して API を設計する場合
  • キュー、イベント、キャッシュ、バックグラウンドジョブを追加する場合

仕組み

  • 明確な境界(コントローラー -> サービス/アクション -> モデル)でアプリを構造化します。
  • 明示的なバインディングとスコープバインディングを使用してルーティングを予測可能にし、アクセス制御のために認可を実施します。
  • 型付きモデル、キャスト、スコープを優先してドメインロジックの一貫性を維持します。
  • I/O の重い処理はキューに、高コストな読み取りはキャッシュにオフロードします。
  • 設定を config/* に集中管理し、環境を明示的にします。

例

プロジェクト構造

明確なレイヤー境界(HTTP、サービス/アクション、モデル)を持つ従来の Laravel レイアウトを使用します。

推奨レイアウト

app/
├── Actions/            # 単一目的のユースケース
├── Console/
├── Events/
├── Exceptions/
├── Http/
│   ├── Controllers/
│   ├── Middleware/
│   ├── Requests/       # フォームリクエストバリデーション
│   └── Resources/      # API リソース
├── Jobs/
├── Models/
├── Policies/
├── Providers/
├── Services/           # ドメインサービスを調整
└── Support/
config/
database/
├── factories/
├── migrations/
└── seeders/
resources/
├── views/
└── lang/
routes/
├── api.php
├── web.php
└── console.php

コントローラー -> サービス -> アクション

コントローラーは薄く保ちます。オーケストレーションはサービスに、単一目的のロジックはアクションに委ねます。

final class CreateOrderAction
{
    public function __construct(private OrderRepository $orders) {}

    public function handle(CreateOrderData $data): Order
    {
        return $this->orders->create($data);
    }
}

final class OrdersController extends Controller
{
    public function __construct(private CreateOrderAction $createOrder) {}

    public function store(StoreOrderRequest $request): JsonResponse
    {
        $order = $this->createOrder->handle($request->toDto());

        return response()->json([
            'success' => true,
            'data' => OrderResource::make($order),
            'error' => null,
            'meta' => null,
        ], 201);
    }
}

ルーティングとコントローラー

明確さのために、ルートモデルバインディングとリソースコントローラーを優先します。

use Illuminate\Support\Facades\Route;

Route::middleware('auth:sanctum')->group(function () {
    Route::apiResource('projects', ProjectController::class);
});

ルートモデルバインディング(スコープ)

スコープバインディングを使用して、クロステナントアクセスを防ぎます。

Route::scopeBindings()->group(function () {
    Route::get('/accounts/{account}/projects/{project}', [ProjectController::class, 'show']);
});

ネストされたルートとバインディング名

  • プレフィックスとパスを一貫させ、二重ネスト(例:conversation と conversations)を避けます。
  • バインドされたモデルに一致する単一のパラメータ名(例:Conversation に対して {conversation})を使用します。
  • ネスト時にはスコープバインディングを優先して、親子関係を強制します。
use App\Http\Controllers\Api\ConversationController;
use App\Http\Controllers\Api\MessageController;
use Illuminate\Support\Facades\Route;

Route::middleware('auth:sanctum')->prefix('conversations')->group(function () {
    Route::post('/', [ConversationController::class, 'store'])->name('conversations.store');

    Route::scopeBindings()->group(function () {
        Route::get('/{conversation}', [ConversationController::class, 'show'])
            ->name('conversations.show');

        Route::post('/{conversation}/messages', [MessageController::class, 'store'])
            ->name('conversation-messages.store');

        Route::get('/{conversation}/messages/{message}', [MessageController::class, 'show'])
            ->name('conversation-messages.show');
    });
});

パラメータを別のモデルクラスに解決したい場合は、明示的なバインディングを定義します。カスタムバインディングロジックには、Route::bind() を使用するか、モデルに resolveRouteBinding() を実装します。

use App\Models\AiConversation;
use Illuminate\Support\Facades\Route;

Route::model('conversation', AiConversation::class);

サービスコンテナバインディング

明確な依存関係配線のために、サービスプロバイダでインターフェースを実装にバインドします。

use App\Repositories\EloquentOrderRepository;
use App\Repositories\OrderRepository;
use Illuminate\Support\ServiceProvider;

final class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind(OrderRepository::class, EloquentOrderRepository::class);
    }
}

Eloquent モデルパターン

モデル設定

final class Project extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'owner_id', 'status'];

    protected $casts = [
        'status' => ProjectStatus::class,
        'archived_at' => 'datetime',
    ];

    public function owner(): BelongsTo
    {
        return $this->belongsTo(User::class, 'owner_id');
    }

    public function scopeActive(Builder $query): Builder
    {
        return $query->whereNull('archived_at');
    }
}

カスタムキャストと値オブジェクト

厳格な型付けには、enum または値オブジェクトを使用します。

use Illuminate\Database\Eloquent\Casts\Attribute;

protected $casts = [
    'status' => ProjectStatus::class,
];
protected function budgetCents(): Attribute
{
    return Attribute::make(
        get: fn (int $value) => Money::fromCents($value),
        set: fn (Money $money) => $money->toCents(),
    );
}

N+1 問題を避けるための Eager Loading

$orders = Order::query()
    ->with(['customer', 'items.product'])
    ->latest()
    ->paginate(25);

複雑なフィルターのためのクエリオブジェクト

final class ProjectQuery
{
    public function __construct(private Builder $query) {}

    public function ownedBy(int $userId): self
    {
        $query = clone $this->query;

        return new self($query->where('owner_id', $userId));
    }

    public function active(): self
    {
        $query = clone $this->query;

        return new self($query->whereNull('archived_at'));
    }

    public function builder(): Builder
    {
        return $this->query;
    }
}

グローバルスコープとソフトデリート

デフォルトのフィルタリングにはグローバルスコープ、復元可能なレコードには SoftDeletes を使用します。 同じフィルターに対して、レイヤー化された動作を意図しない限り、グローバルスコープと名前付きスコープの両方は使用しないでください。

use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Builder;

final class Project extends Model
{
    use SoftDeletes;

    protected static function booted(): void
    {
        static::addGlobalScope('active', function (Builder $builder): void {
            $builder->whereNull('archived_at');
        });
    }
}

再利用可能なフィルターのためのクエリスコープ

use Illuminate\Database\Eloquent\Builder;

final class Project extends Model
{
    public function scopeOwnedBy(Builder $query, int $userId): Builder
    {
        return $query->where('owner_id', $userId);
    }
}

// サービス、リポジトリなどで使用
$projects = Project::ownedBy($user->id)->get();

複数ステップ更新のためのトランザクション

use Illuminate\Support\Facades\DB;

DB::transaction(function (): void {
    $order->update(['status' => 'paid']);
    $order->items()->update(['paid_at' => now()]);
});

マイグレーション

命名規則

  • ファイル名はタイムスタンプを使用:YYYY_MM_DD_HHMMSS_create_users_table.php
  • マイグレーションは匿名クラスを使用(名前付きクラスは不要)。ファイル名が意図を伝えます
  • テーブル名はデフォルトで snake_case かつ複数形

マイグレーションの例

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('orders', function (Blueprint $table): void {
            $table->id();
            $table->foreignId('customer_id')->constrained()->cascadeOnDelete();
            $table->string('status', 32)->index();
            $table->unsignedInteger('total_cents');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('orders');
    }
};

フォームリクエストとバリデーション

バリデーションはフォームリクエストに保持し、入力を DTO に変換します。

use App\Models\Order;

final class StoreOrderRequest extends FormRequest
{
    public function authorize(): bool
    {
        return $this->user()?->can('create', Order::class) ?? false;
    }

    public function rules(): array
    {
        return [
            'customer_id' => ['required', 'integer', 'exists:customers,id'],
            'items' => ['required', 'array', 'min:1'],
            'items.*.sku' => ['required', 'string'],
            'items.*.quantity' => ['required', 'integer', 'min:1'],
        ];
    }

    public function toDto(): CreateOrderData
    {
        return new CreateOrderData(
            customerId: (int) $this->validated('customer_id'),
            items: $this->validated('items'),
        );
    }
}

API リソース

リソースとページネーションで API レスポンスを一貫させます。

$projects = Project::query()->active()->paginate(25);

return response()->json([
    'success' => true,
    'data' => ProjectResource::collection($projects->items()),
    'error' => null,
    'meta' => [
        'page' => $projects->currentPage(),
        'per_page' => $projects->perPage(),
        'total' => $projects->total(),
    ],
]);

イベント、ジョブ、キュー

  • 副作用(メール、分析)のためにドメインイベントを発行します
  • 遅い処理(レポート、エクスポート、ウェブフック)にはキューに投入されたジョブを使用します
  • リトライとバックオフを持つべき等性のあるハンドラーを優先します

キャッシュ

  • 読み取り負荷の高いエンドポイントと高コストなクエリをキャッシュします
  • モデルイベント(作成/更新/削除)でキャッシュを無効化します
  • 関連データをキャッシュする場合はタグを使用して、簡単に無効化できるようにします

設定と環境

  • シークレットは .env に、設定は config/*.php に保持します
  • 環境ごとの設定オーバーライドを使用し、本番環境では config:cache を実行します

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

関連スキル