aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Web Geliştirme

Laravel API Yapımı: RESTful Endpoint Tasarımı

Laravel api yapımı, doğru kurulduğunda hem mobil uygulamanın hem de tek sayfalık (SPA) ön yüzün üzerine güvenle inşa edilebileceği sağlam bir temel sunar. Bu yazıda boş bir endpoint listesinden değil; tutarlı bir kaynak (resource) modeli, temiz bir JSON çıktısı ve geleceğe dönük bir sürümleme stratejisinden yola çıkarak gerçek bir REST API tasarlayacağız. Amaç, "çalışan" bir API değil; bakımı kolay, öngörülebilir ve istemcilerin güvendiği bir API kurmak.

REST ve kaynak odaklı düşünmek

RESTful tasarımın özü, eylemleri değil kaynakları URL'lere yerleştirmektir. Yani /api/createPost gibi fiil içeren adresler yerine, kaynağı isimle ifade edip eylemi HTTP metoduna bırakırsın:

  • GET /api/posts — listele
  • POST /api/posts — oluştur
  • GET /api/posts/{id} — tek kayıt göster
  • PUT/PATCH /api/posts/{id} — güncelle
  • DELETE /api/posts/{id} — sil

Laravel bu kalıbı doğrudan destekler. Route::apiResource() tanımı, yukarıdaki beş rotayı tek satırda üretir; web.php'deki klasik resource'tan farkı, form gösteren create ve edit rotalarını atlamasıdır — çünkü bir API'de HTML form yoktur.

Resource controller ile rotaları kurmak

Önce --api bayrağıyla bir controller üret:

php artisan make:controller Api/V1/PostController --api --model=Post

Ardından routes/api.php içinde tek satırla bağla:

use App\Http\Controllers\Api\V1\PostController;

Route::apiResource('posts', PostController::class);

Bu, otomatik olarak index, store, show, update ve destroy metotlarını uygun HTTP fiillerine eşler. {post} rota parametresi, model türü ipucu verildiğinde Laravel'in route model binding özelliğiyle doğrudan ilgili Post nesnesine dönüşür; bulunamazsa Laravel kendiliğinden 404 üretir:

public function show(Post $post)
{
    return new PostResource($post);
}

API Resource ile JSON çıktısını biçimlendirmek

Modeli doğrudan return $post; ile döndürmek işe yarar ama tehlikelidir: veritabanındaki her sütun (ör. iç notlar, password, zaman damgaları) olduğu gibi dışarı sızar ve şema her değiştiğinde istemci kırılır. Bunun yerine API Resource sınıfı kullan; bu, modelin JSON temsilini açıkça tanımladığın bir dönüşüm katmanıdır.

php artisan make:resource PostResource

Sonra hangi alanların, hangi adla dışarı çıkacağını sen belirlersin:

public function toArray($request): array
{
    return [
        'id'         => $this->id,
        'title'      => $this->title,
        'body'       => $this->body,
        'author'     => new UserResource($this->whenLoaded('user')),
        'created_at' => $this->created_at->toIso8601String(),
    ];
}

whenLoaded() ilişkisel veriyi yalnızca gerçekten eager-load edildiğinde ekler; bu, N+1 sorgu problemini önlemenin pratik bir yoludur. Bir koleksiyon döndürmek için PostResource::collection($posts) kullanırsın. Eğer toplam sayfa sayısı gibi meta veriyi de döndürmek istiyorsan, index içinde doğrudan bir paginator'ı resource'a verebilirsin; Laravel sayfalama bağlantılarını links ve meta altında otomatik üretir.

Doğrulama ve hata yanıtları

Gelen veriyi controller'ı şişirmeden doğrulamak için Form Request sınıfları idealdir:

php artisan make:request StorePostRequest
public function rules(): array
{
    return [
        'title' => ['required', 'string', 'max:255'],
        'body'  => ['required', 'string'],
    ];
}

Controller metodunda tür ipucu verdiğinde Laravel isteği otomatik doğrular; kural ihlalinde, Accept: application/json başlığı gönderen bir istemciye 422 Unprocessable Content durum kodu ve alan bazlı hata mesajları döner. Bu, REST API'lerde tutarlı hata sözleşmesinin temelidir: 200/201 başarı, 401 kimlik doğrulama eksik, 403 yetki yok, 404 kayıt yok, 422 doğrulama hatası. Bu kodları tutarlı kullanmak, istemci tarafındaki hata yönetimini öngörülebilir kılar.

Sürümleme: API'yi geleceğe hazırlamak

Bir API yayınlandıktan sonra onu kullanan istemcileri kırmadan değiştirmek zorlaşır. Çözüm sürümlemedir. En yaygın ve en açık yöntem, sürümü URL yoluna koymaktır:

Route::prefix('v1')->group(function () {
    Route::apiResource('posts', \App\Http\Controllers\Api\V1\PostController::class);
});

Böylece /api/v1/posts kararlı kalır; ileride uyumsuz bir değişiklik gerektiğinde V2 namespace'i ve v2 prefix'iyle yeni bir sürüm açar, eskisini bir süre çalışır tutarsın. Controller'ları App\Http\Controllers\Api\V1 gibi sürüm klasörlerine ayırmak, kod tabanını da fiziksel olarak temiz tutar. Alternatif olarak sürümü Accept başlığında taşımak (media type versioning) mümkündür, ancak URL tabanlı yaklaşım hem tarayıcıda denemek hem de loglarda izlemek açısından daha pratiktir.

Kimlik doğrulama ve hız sınırlama

Herkese açık olmayan endpoint'leri korumak için Laravel'in Sanctum paketi, hem SPA çerez tabanlı oturumlar hem de token tabanlı erişim için tercih edilen çözümdür. Korunan rotaları auth:sanctum middleware'iyle gruplarsın:

Route::middleware('auth:sanctum')->group(function () {
    Route::apiResource('posts', PostController::class)
        ->except(['index', 'show']);
});

Burada okuma uçları herkese açık, yazma uçları kimlik doğrulamalı kalır. Ayrıca kötüye kullanımı engellemek için throttle middleware'iyle hız sınırı koymak iyi bir alışkanlıktır; Laravel RateLimiter ile dakika başına istek sayısını kullanıcı veya IP bazında tanımlamana izin verir.

Sık Sorulan Sorular

apiResource ile normal resource arasındaki fark nedir?

Route::resource() yedi rota üretir ve bunlardan ikisi (create, edit) HTML form göstermeye yöneliktir. Route::apiResource() bu ikisini atlar ve yalnızca veri döndüren beş rotayı bırakır — bir JSON API'de form gösterimi olmadığı için tam ihtiyacın olan budur.

Modeli doğrudan döndürmek yerine neden API Resource kullanmalıyım?

Çünkü API Resource, dış sözleşme ile veritabanı şemanı birbirinden ayırır. Sütun adı değiştirsen veya hassas bir alan eklesen bile dışarı çıkan JSON, sen istemedikçe değişmez ya da sızmaz. Bu, hem güvenlik hem de geriye dönük uyumluluk için kritiktir.

Sürümlemeye baştan ihtiyacım var mı?

Tek bir küçük istemci için v1 prefix'i şart değildir, ama eklemenin maliyeti neredeyse sıfırdır. Yolu en baştan /api/v1 olarak kurmak, ileride kırıcı bir değişiklik gerektiğinde sana büyük bir esneklik kazandırır; sonradan eklemek ise tüm istemcileri taşımayı gerektirir.

API'n için sağlam bir temel mi istiyorsun? Resource controller'lardan sürümlemeye ve kimlik doğrulamaya kadar ölçeklenebilir bir Laravel REST API tasarlamana yardımcı olabilirim — benimle iletişime geç ve projeni birlikte planlayalım.

Devamı için