Laravel ile RESTful API Geliştirme: Uygulanabilir Pratikler
Bu rehber, Laravel'in API geliştirme için sunduğu araçları orta seviye bir geliştiricinin günlük iş akışına oturtmayı hedefler. Sürüme bağlı davranış farkları bulunduğundan, kullandığınız Laravel sürümünün resmi dokümantasyonunu esas alın; burada anlatılan yapı taşları (kaynak yönlendirme, form request, API Resource, policy) Laravel 8 ve sonrasında benzer mantıkla çalışır.
Önkoşul olarak şunları varsayıyorum: temel PHP ve Composer bilgisi, bir Laravel projesi kurmuş olmak, Eloquent ile model ve migration yazabilmek.
Kaynakları Route Dosyasında Toplayın
API rotalarını routes/api.php içinde tanımlayın. Bu dosyadaki rotalar varsayılan olarak api middleware grubuna ve /api ön ekine bağlanır. Tek tek GET, POST, PUT, DELETE satırları yazmak yerine kaynak yönlendirmeyi kullanın:
use App\Http\Controllers\PostController;
Route::apiResource('posts', PostController::class);
apiResource, index, store, show, update, destroy eylemlerini tek satırda tanımlar; içerik düzenleme formu için gereken create ve edit rotalarını eklemez. Bu, JSON API için doğru varsayılandır.
Sürümleme gerekiyorsa ön eki route grubuyla verin:
Route::prefix('v1')->group(function () {
Route::apiResource('posts', PostController::class);
});
Sürümü URL'de tutmak, istemcilerin hangi sözleşmeye konuştuğunu açıkça görmesini sağlar.
Doğrulamayı Controller'dan Çıkarın
Gelen veriyi controller içinde $request->validate([...]) ile doğrulamak çalışır, ancak kurallar büyüdükçe controller şişer. Form request sınıfları doğrulamayı ayrı bir yere taşır ve yeniden kullanılabilir kılar:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePostRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'title' => ['required', 'string', 'max:255'],
'body' => ['required', 'string'],
];
}
}
Controller tarafında tip belirterek enjekte edin; Laravel doğrulamayı istek controller'a ulaşmadan çalıştırır ve başarısız olursa otomatik olarak hata yanıtı üretir:
public function store(StorePostRequest $request)
{
$post = Post::create($request->validated());
return response()->json($post, 201);
}
$request->validated() yalnızca kurallardan geçen alanları döndürür. Böylece istemcinin gönderdiği fazladan alanların modele sızmasını engellersiniz. Doğrudan $request->all() ile create çağırmak, kullanıcının is_admin gibi bir alanı gönderip yetki yükseltmesine yol açabilir; bu, en sık yapılan güvenlik hatalarından biridir.
Yanıt Gövdesini API Resource ile Şekillendirin
Eloquent modelini doğrudan return $post; şeklinde döndürmek, veritabanı sütunlarınızı olduğu gibi dışarı açar. İç alanlar, ilişki kimlikleri ve ileride eklenecek hassas sütunlar istemciye sızabilir. API Resource katmanı, dışa açılan alanları açıkça belirlemenizi sağlar:
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class PostResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'body' => $this->body,
'created_at' => $this->created_at->toIso8601String(),
];
}
}
Controller'da tek kayıt için new PostResource($post), liste için PostResource::collection($posts) döndürün. Resource, sayfalamayı da otomatik olarak meta ve links alanlarıyla paketler.
Kimlik Doğrulama ve Yetkilendirmeyi Ayırın
Kimlik doğrulama "kim olduğunuzu", yetkilendirme "ne yapabileceğinizi" belirler. İkisini karıştırmak, giriş yapmış herkesin her kaynağa erişebildiği bir API üretir.
Token tabanlı kimlik doğrulama için Laravel Sanctum yaygın tercihtir. Korumak istediğiniz rota grubuna auth:sanctum middleware'ini ekleyin:
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('posts', PostController::class);
});
Kayıt bazlı yetki için policy kullanın. update ve destroy gibi eylemlerde, kullanıcının o kaydın sahibi olup olmadığını controller içinde kontrol edin:
public function update(UpdatePostRequest $request, Post $post)
{
$this->authorize('update', $post);
$post->update($request->validated());
return new PostResource($post);
}
authorize çağrısını atlamak, başka bir kullanıcının kaydını değiştirmeye izin veren bir açık yaratır. Bunu her yazma eyleminde uygulayın.
HTTP Durum Kodlarını Doğru Kullanın
REST sözleşmesinin okunabilirliği büyük ölçüde durum kodlarına bağlıdır. Yaygın eşleşmeler:
200başarılı okuma ve güncelleme201yeni kayıt oluşturma204gövdesiz başarılı silme401kimlik doğrulanmamış403kimlik doğrulanmış ama yetkisiz404kaynak yok422doğrulama hatası
Doğrulama başarısız olduğunda Laravel form request ile otomatik olarak 422 ve alan bazlı hata listesi döndürür; bunu elle yeniden üretmenize gerek yoktur.
Yaygın Hatalar
- N+1 sorgu problemi: Liste dönerken ilişkili veriyi her kayıt için ayrı sorgulamak. Resource içinde ilişki kullanıyorsanız controller'da
Post::with('author')->paginate()gibi eager loading uygulayın. - İş mantığını controller'a yığmak: Yan etkileri (bildirim gönderme, dosya işleme) servis sınıflarına taşımak, controller'ı ince tutar ve test etmeyi kolaylaştırır.
$request->all()ile toplu atama: Yukarıda değinildiği gibi yetki yükseltme riski taşır;validated()kullanın.- Tutarsız yanıt biçimi: Bazı uç noktalarda sarmalanmış, bazılarında çıplak JSON dönmek istemci tarafını zorlar. Resource katmanını her yerde kullanarak biçimi tekilleştirin.
- Anlamlı hata mesajı vermemek:
422gövdesinde hangi alanın neden reddedildiğini belirtin; hata ayıklamayı hem siz hem istemci tarafı kolaylaştırırsınız.
Toplu Atama ve Kütle Atama Koruması
Model tarafında $fillable ile hangi alanların toplu atanabileceğini açıkça listeleyin:
protected $fillable = ['title', 'body'];
$guarded = [] kullanmak, tüm alanları toplu atamaya açar; doğrulama katmanı bir gün gevşerse bu doğrudan güvenlik açığına dönüşür. $fillable beyaz liste yaklaşımıdır ve tercih edilmelidir.
Rate Limiting ve Diğer Güvenlik Notları
API rotalarına istek sınırı uygulamak, kaba kuvvet ve kötüye kullanımı azaltır. Laravel'de throttle middleware'i bu iş için kullanılır; sınır değerini uygulamanızın gerçek trafiğine göre belirleyin.
Bunun yanında:
- Hassas veriyi yanıt gövdesine koymayın; Resource katmanı bunun için ilk savunma hattıdır.
- Hata yanıtlarında yığın izini (stack trace) istemciye göstermeyin; üretimde
APP_DEBUGkapalı olmalıdır. - CORS politikasını yalnızca gerçekten hizmet verdiğiniz kaynaklara açın;
*ile herkese açmak, tarayıcı tabanlı istemcilerde beklenmedik erişimlere yol açar.
Kapanış
Laravel'in kaynak yönlendirme, form request, API Resource ve policy katmanları, RESTful bir API'nin iskeletini az kodla kurmanızı sağlar. Kritik olan, her katmanın sorumluluğunu net tutmak: doğrulama istekte, yetki policy'de, çıktı biçimi Resource'ta, iş mantığı servislerde. Bu ayrımı koruduğunuzda hem güvenlik açıklarına karşı savunmanız güçlenir hem de API'niz büyüdükçe bakımı yönetilebilir kalır.