laravel-api-architect

from anilcancakir/my-claude-code

Production-grade Claude Code setup: plugins, MCP servers, skills, and performance optimizations.

3 stars0 forksUpdated Jan 26, 2026
npx skills add https://github.com/anilcancakir/my-claude-code --skill laravel-api-architect

SKILL.md

Laravel API Architect

Production-grade API development with Service-Repository pattern for PHP 8.4+ and Laravel 12+.

Core Principles

  1. Thin Controllers - HTTP concerns only, delegate business logic to Services
  2. Service Layer - Business logic, transactions, events
  3. Repository Layer - Complex queries (optional, use when needed)
  4. Type Everything - Return types, parameter types, property types
  5. Form Requests - Validation never in controllers
  6. API Resources - Response transformation, never return models directly

Architecture Quick Reference

LayerResponsibilityDepends On
ControllerHTTP request/responseServices, FormRequests
ServiceBusiness logic, transactionsRepositories, Models, Events
RepositoryComplex/reusable queriesModels
ModelData, relationships, scopesOther Models only

Essential Patterns

Controller Pattern

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\StoreOrderRequest;
use App\Http\Resources\OrderResource;
use App\Models\Order;
use App\Services\OrderService;
use Illuminate\Http\JsonResponse;
use Symfony\Component\HttpFoundation\Response;

final class OrderController extends Controller
{
    public function __construct(
        private readonly OrderService $orderService
    ) {}

    public function index(): JsonResponse
    {
        $orders = Order::query()
            ->forUser(auth()->id())
            ->with(['items'])
            ->latest()
            ->paginate(15);

        return response()->json(OrderResource::collection($orders));
    }

    public function store(StoreOrderRequest $request): JsonResponse
    {
        $order = $this->orderService->create($request->validated());

        return response()->json(
            new OrderResource($order),
            Response::HTTP_CREATED
        );
    }

    public function show(Order $order): JsonResponse
    {
        $this->authorize('view', $order);
        
        return response()->json(
            new OrderResource($order->load(['items', 'payments']))
        );
    }

    public function destroy(Order $order): JsonResponse
    {
        $this->authorize('delete', $order);
        $order->delete();
        
        return response()->json(null, Response::HTTP_NO_CONTENT);
    }
}

Service Pattern

<?php


namespace App\Services;

use App\Events\OrderCreated;
use App\Models\Order;
use Illuminate\Support\Facades\DB;

final class OrderService
{
    public function create(array $data): Order
    {
        return DB::transaction(function () use ($data): Order {
            $order = Order::query()->create([
                'user_id' => auth()->id(),
                'status' => OrderStatus::Pending,
                'total' => $data['total'],
            ]);

            $order->items()->createMany($data['items']);

            event(new OrderCreated($order));

            return $order->load('items');
        });
    }
}

Form Request Pattern

<?php


namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

final class StoreOrderRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'total' => ['required', 'numeric', 'min:0'],
            'items' => ['required', 'array', 'min:1'],
            'items.*.product_id' => [
                'required',
                Rule::exists('products', 'id')->where('active', true),
            ],
            'items.*.quantity' => ['required', 'integer', 'min:1', 'max:100'],
        ];
    }
}

API Resource Pattern

<?php


namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

final class OrderResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'status' => $this->status->value,
            'total' => $this->total,
            'created_at' => $this->created_at->toISOString(),
            
            // Conditional relationships
            'user' => new UserResource($this->whenLoaded('user')),
            'items' => OrderItemResource::collection($this->whenLoaded('items')),
            
            // Conditional attributes
            'can_cancel' => $this->when(
                $request->user()?->can('cancel', $this->resource),
                true
            ),
        ];
    }
}

References

Load detailed patterns as needed:

TopicReferenceWhen to Load
Sanctum authenticationreferences/sanctum.mdToken auth, SPA auth, abilities
Passport OAuthreferences/passport.mdOAuth2, third-party apps
Service-Reposi

...

Read full content

Repository Stats

Stars3
Forks0
LicenseMIT License