本文へ移動
cccskills
無料GitHub で公開

laravel-conventions

Consolidated Laravel project conventions: Action pattern, Form Requests, Policies, routing, Inertia integration, code style. Apply when: writing or reviewing Laravel backend code (controllers, actions, requests, policies, providers). Activated automatically by laravel-plugin/stack.md as a convention skill for the development phase.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md8.0 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Laravel Conventions

This skill encodes the conventions used across modern Laravel + Inertia + Vue projects. Apply when implementing features in such projects.

1. Routing

Web vs API

  • routes/web.php — Inertia / browser-driven flows. Has session, CSRF, web middleware.
  • routes/api.php — JSON-only flows. Stateless. Token-authenticated.

Don't put Inertia render calls in api.php. Don't put JSON-API endpoints in web.php (use a separate /api/internal/... namespace if absolutely needed).

Route style

// Preferred: explicit routes with action classes
Route::post('subscriptions', CreateSubscriptionAction::class)
    ->name('subscriptions.store')
    ->middleware(['auth', 'verified']);

// Acceptable: resource controllers for plain CRUD
Route::resource('subscriptions', SubscriptionController::class)
    ->only(['index', 'show', 'store', 'destroy']);

// Avoid: closures in routes (no caching, no testability)
// Route::post('subscriptions', function (Request $r) { ... });  // DON'T

2. Action pattern (preferred for non-trivial business logic)

A single-action invokable class that does one thing.

namespace App\Actions;

use App\Models\Subscription;
use App\Http\Requests\StoreSubscriptionRequest;
use Inertia\Response;

class CreateSubscriptionAction
{
    public function __invoke(StoreSubscriptionRequest $request): Response
    {
        $this->authorize('create', Subscription::class);

        $subscription = DB::transaction(function () use ($request) {
            $stripeCustomer = app(StripeClient::class)->customers->create([
                'email' => $request->user()->email,
            ]);

            return Subscription::create([
                'user_id' => $request->user()->id,
                'stripe_customer_id' => $stripeCustomer->id,
                'status' => 'trialing',
                ...$request->validated(),
            ]);
        });

        SubscriptionCreated::dispatch($subscription);

        return Inertia::render('Subscription/Show', [
            'subscription' => $subscription,
        ]);
    }
}

When to prefer Action over Controller method:

  • Logic spans 3+ steps
  • Uses transactions
  • Dispatches events / jobs
  • Will be invoked from multiple places (e.g., HTTP + queue worker)

When a plain controller method is fine:

  • Single Eloquent operation
  • No side effects
  • Simple resource CRUD

3. Form Requests for validation

Always extract validation into a Form Request class. Never inline $request->validate().

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreSubscriptionRequest extends FormRequest
{
    public function authorize(): bool
    {
        return $this->user()->can('create', Subscription::class);
    }

    public function rules(): array
    {
        return [
            'plan' => ['required', 'string', 'in:basic,pro,enterprise'],
            'starts_at' => ['nullable', 'date', 'after_or_equal:today'],
            'payment_method_id' => ['required', 'string'],
        ];
    }

    public function messages(): array
    {
        return [
            'plan.in' => 'Plan must be one of: basic, pro, enterprise.',
        ];
    }
}

The authorize() method is the first line of defense — ALWAYS implement it. Returning true blindly defeats Laravel's auth pipeline.

4. Policies for authorization

Every model that has owner-or-admin access patterns gets a Policy.

namespace App\Policies;

use App\Models\Subscription;
use App\Models\User;

class SubscriptionPolicy
{
    public function view(User $user, Subscription $subscription): bool
    {
        return $user->id === $subscription->user_id || $user->isAdmin();
    }

    public function update(User $user, Subscription $subscription): bool
    {
        return $user->id === $subscription->user_id;
    }

    public function delete(User $user, Subscription $subscription): bool
    {
        return $user->isAdmin();
    }
}

Register in AuthServiceProvider::$policies. Use via $this->authorize('update', $subscription) in actions/controllers, or Gate::authorize('update', $subscription).

Never inline role checks: if ($user->role === 'admin') { ... } — that bypasses Laravel's auth pipeline and makes testing harder.

5. Eloquent models

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;

class Subscription extends Model
{
    use SoftDeletes;

    protected $fillable = [
        'user_id',
        'stripe_customer_id',
        'plan',
        'status',
        'starts_at',
        'ends_at',
    ];

    protected $casts = [
        'starts_at' => 'datetime',
        'ends_at'   => 'datetime',
        'amount'    => 'decimal:2',
    ];

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    protected function isActive(): Attribute
    {
        return Attribute::get(fn () => $this->status === 'active' && $this->ends_at?->isFuture());
    }
}
  • $fillable is mandatory. Never $guarded = [].
  • $casts for everything that isn't a string.
  • Relations use return-type declarations (BelongsTo, HasMany).
  • Use Attribute::get() for computed properties — clean and cacheable.

6. Inertia integration

Pass typed data to Inertia pages:

return Inertia::render('Subscription/Show', [
    'subscription' => fn () => SubscriptionResource::make($subscription),
    'paymentMethods' => fn () => PaymentMethodResource::collection($user->paymentMethods),
]);

Use closures for lazy props — Inertia only evaluates them on full reload, not partial.

API Resources prevent leaking model internals to the frontend:

class SubscriptionResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'plan' => $this->plan,
            'status' => $this->status,
            'starts_at' => $this->starts_at?->toISOString(),
            // NEVER $this->stripe_customer_id — stays internal
        ];
    }
}

7. Code style

General PHP style (PSR-12, declare(strict_types=1), enums, readonly, single quotes, fn arrow functions) lives in php-foundation:php-conventions — follow it. Laravel-specific additions on top:

  • Pint runs auto-fix on the Stop hook (laravel-plugin provides one) — do not hand-tune whitespace Pint owns.
  • PHPStan / Larastan level 6+ where the project supports it.

8. Anti-patterns to avoid

Don'tDo
$request->all() into modelSpecify fields, or use $request->validated()
User::where('role', 'admin')->get()Add a scope: User::admins()->get()
Logic in Blade templatesMove to Action / Resource / view-helper
Eager-load everywhereEager-load only what the view needs (use with() selectively)
DB::raw('...') with concatenationParameter bindings always
Closure in routesAction class or controller

9. Checklist before completing development phase

  • All new routes have explicit middleware (auth, verified, etc.)
  • All Form Requests have authorize() returning a real check
  • All Policies registered in AuthServiceProvider
  • All models have $fillable (never $guarded = [])
  • All datetime/decimal columns have $casts
  • All Inertia pages get typed data through Resources, not raw models
  • ./vendor/bin/pint clean
  • php -l <changed-file> passes for each changed PHP file

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Angular 18-21 project structure, standalone components vs NgModule, control flow (@if/@for/@switch + *ngIf/*ngFor legacy), decorators, dependency injection (inject() function), lifecycle hooks, pipes, Angular Universal SSR pointer. Use this skill to: - Detect project style (standalone vs NgModule) and apply matching patterns. - Pick correct decorators and DI approach. - Use modern control flow (@if/@for/@switch) in Angular 17+ projects. - Apply `inject()` function over constructor injection where appropriate. - Wire bootstrap correctly (bootstrapApplication for standalone, AppModule for legacy). Do NOT use this skill for: - State management (see angular-state-and-rx). - Routing (see angular-routing). - Forms (see angular-forms). - Testing (see angular-testing).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

Angular forms: Reactive Forms (preferred — typed FormGroup/FormControl since Angular 14, FormBuilder, custom + async validators, FormArray, multi-step) and Template-driven (`[(ngModel)]` + FormsModule). Validation strategies, server error mapping, accessibility. Use this skill to: - Build Reactive Forms with typed FormGroup/FormControl. - Use FormBuilder для concise syntax. - Implement custom synchronous and async validators. - Wire FormArray for dynamic field lists. - Map server errors back to form fields. - Pick Reactive vs Template-driven (prefer Reactive). Do NOT use this skill for: - General conventions (see angular-conventions). - State management beyond forms (see angular-state-and-rx). - Routing (see angular-routing). - Testing forms (see angular-testing).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

Angular Router (built-in `@angular/router`) — route configuration for standalone and NgModule projects, functional guards (Angular 14.1+), lazy loading, route resolvers, typed params via signals/observables, programmatic navigation, route data and meta. Use this skill to: - Configure routes (standalone-style or NgModule-style). - Use functional guards (canActivate as function, preferred over class-based in 17+). - Lazy-load components or feature modules. - Implement auth guards via route meta + functional guards. - Read params/queries via `inject(ActivatedRoute)` + signals or RxJS. Do NOT use this skill for: - General conventions (see angular-conventions). - State management (see angular-state-and-rx). - Forms (see angular-forms). - Testing routes (see angular-testing).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

State management for Angular 18-21: signals (signal/computed/effect), services-as-state, NgRx Store + Effects + Selectors, NgRx Component Store, NgRx Signals (newer signal-based store). RxJS essentials — operators, async pipe, takeUntilDestroyed, signal/observable interop. Use this skill to: - Pick the right state tool (signals / services / NgRx variant / vue-query equivalent). - Use signals correctly (signal/computed/effect — when each). - Build a Pinia-style service-as-state singleton. - Set up NgRx Store + Effects + Selectors. - Use RxJS without leaking subscriptions (async pipe, takeUntilDestroyed, Subject patterns). - Bridge signals ↔ observables via toSignal / toObservable. Do NOT use this skill for: - General Angular conventions (see angular-conventions). - Routing state (see angular-routing). - Form state (see angular-forms). - Testing state (see angular-testing).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

Testing Angular 18-21: TestBed, component harnesses (@angular/cdk/testing), Karma+Jasmine (default historical) vs Jest (jest-preset-angular, modern), Angular Testing Library (RTL-style). HttpClient mocking via HttpTestingController. NgRx Effects testing. Cypress / Playwright e2e. Use this skill to: - Detect runner (Karma+Jasmine vs Jest) and configure correctly. - Write component tests with TestBed. - Use component harnesses for Material / custom UI components. - Mock HttpClient via provideHttpClientTesting + HttpTestingController. - Test signal-based inputs with componentRef.setInput(). - Test NgRx Effects with provideMockActions. Do NOT use this skill for: - General Angular conventions (see angular-conventions). - Routing patterns broadly (see angular-routing — covers testing routes briefly). - Form patterns broadly (see angular-forms).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

Shared conventions for every SDLC development-phase architect agent: hard rules, code quality bar, workflow steps (superpowers invocation, spec reading, codebase exploration, verification), and the report/compact-summary contract. Architects load this skill first, then apply their stack-specific instructions on top.

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

AratKruglik のスキルをすべて見る

このスキルの問題を報告する