REST API v Laravelu se Sanctum a API Resources

Jak v Laravelu postavím REST API — verzované routy, autentizace přes Sanctum tokeny, API Resources, Form Requesty a rate limiting.
Publikováno 14.08.2026

REST API v Laravelu se Sanctum a API Resources

Publikováno

· Autor: · Pod kapotou · 3 min čtení

Obsah článku

Jakmile má projekt víc kanálů — web, mobilní aplikaci, napojení na cizí systém — potřebuje jedno rozhraní, přes které si všechno povídá. V Laravelu stavím REST API stavebnicí, kterou framework nabízí přímo v boxu: verzované routy, Sanctum tokeny, API Resources a Form Requesty. Ukážu, jak to zapadá dohromady.

Verzované routy a autentizace

API verzuju od prvního dne. Jakmile ho jednou někdo používá, nemůžu měnit strukturu odpovědí bez toho, abych mu rozbil integraci — prefix v1 mi nechá vedle sebe postavit v2, až bude potřeba.

// routes/api.php
use Illuminate\Support\Facades\Route;

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

Autentizaci řeší Sanctum přes bearer tokeny. Klient pošle token v hlavičce, auth:sanctum ho ověří a k requestu připojí uživatele i s jeho oprávněními.

$token = $user->createToken('mobile-app', ['projects:read'])->plainTextToken;

API Resources: konzistentní tvar odpovědi

Nikdy nevracím model přímo — vždycky přes JsonResource. Klient tak dostává stabilní strukturu, kterou můžu měnit na jednom místě, a nehrozí, že omylem vyteče něco z databáze.

class ProjectResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id'           => $this->id,
            'title'        => $this->title,
            'slug'         => $this->slug,
            'technologies' => $this->technologies,
            'published_at' => $this->published_at?->toIso8601String(),
        ];
    }
}

V controlleru se pak vrací jednořádkově a eager loadingem předejdu N+1 dotazům:

return ProjectResource::collection(
    Project::query()->with('images')->published()->paginate(20)
);

Validace přes Form Request

Vstupy nevaliduju v controlleru, ale v samostatném FormRequest. Controller zůstává čitelný a pravidla se dají znovupoužít.

class StoreProjectRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title'   => ['required', 'string', 'max:255'],
            'slug'    => ['required', 'alpha_dash', 'unique:projects,slug'],
            'content' => ['required', 'string'],
        ];
    }
}

Při chybě Laravel sám vrátí 422 se strukturou chyb — druhá strana přesně ví, co je špatně.

Rate limiting

Veřejné API bez limitu je pozvánka k problémům. Limit nastavuju podle uživatele, u nepřihlášených podle IP.

RateLimiter::for('api', fn (Request $request) =>
    Limit::perMinute(60)->by($request->user()?->id ?: $request->ip())
);

Na co nezapomenout

  • Verzuj hned. Přidat v1 na začátku je zdarma, rozdělit neverzované API zpětně je peklo.

  • Bezpečnost je součást návrhu. Tokeny s konkrétními oprávněními (abilities), ne jeden všemocný token.

  • Počítej s výpadky cizích systémů. Volání ven patří do fronty s opakováním, ne do request cyklu.

Závěr

Dobře navržené REST API je páteř, na kterou se pak věší další kanály bez stavění od nuly. Rychlé a bezpečné API stojí na dobrém základu — širší pohled na výkon backendu najdete v článku o optimalizaci výkonu Laravel aplikace a na zabezpečení v článku o HTTPS a bezpečnosti pro majitele webu. Příklady propojených systémů najdete mezi projekty. Plánujete mobilní appku nebo integraci? Napište mi.