Laravel validation, gelen istek verisini kontrollere ulaşmadan önce güvenli ve tutarlı biçimde doğrulamanın en temiz yoludur. İyi kurgulanmış doğrulama, hem kullanıcıya anlaşılır geri bildirim verir hem de veritabanına bozuk veri girmesini engeller. Bu yazıda kural sözdiziminden başlayıp Form Request sınıflarına, özel kurallara ve hata mesajı yönetimine kadar pratikte gerçekten kullandığım yaklaşımı anlatıyorum.
En hızlı yol: controller içinde validate()
Küçük formlar için en pratik yöntem, controller metodunda doğrudan $request->validate() çağırmaktır. Kurallar geçerse kod devam eder; geçmezse Laravel otomatik olarak bir yönlendirme yapar ve hataları session'a koyar (JSON istekte ise 422 döner).
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'email' => 'required|email',
'age' => 'nullable|integer|min:18',
'tags' => 'array',
'tags.*' => 'string|max:30',
]);
Post::create($validated);
return redirect()->route('posts.index');
}
Dikkat edilmesi gereken nokta: validate() yalnızca doğruladığın alanları geri döndürür. Bu, fazladan ve istenmeyen alanların modele sızmasını (mass assignment) engellediği için güvenlik açısından da değerlidir. Kuralları boru ile zincirlemek yerine dizi formunu da kullanabilirsin; özellikle Rule nesneleri içeren karmaşık kurallarda dizi biçimi daha okunabilir olur.
Sık kullanılan kurallar ve mantığı
Laravel'in yüzlerce hazır kuralı vardır. Günlük işte en çok şunlara ihtiyaç duyarsın:
required/nullable— alanın zorunlu mu yoksa boş geçilebilir mi olduğunu belirler.string,integer,boolean,array,date— tip kontrolleri.min/max/between— sayılarda değer, metinlerde karakter, dizilerde eleman sayısı.email,url,uuid— biçim doğrulamaları.unique:table,columnveexists:table,column— veritabanı tabanlı kontroller.confirmed—passwordilepassword_confirmationalanının eşleşmesini ister.
Koşullu kurallar için required_if, required_with, required_without gibi varyantlar hayat kurtarır. Örneğin "ödeme tipi kart ise kart numarası zorunlu olsun" mantığını tek satırda kurabilirsin: 'card_number' => 'required_if:payment,card'.
Form Request: doğrulamayı controller'dan çıkar
Kurallar büyüdükçe controller şişer. Doğru çözüm bir Form Request sınıfı oluşturmaktır. Bu sınıf hem yetki kontrolünü hem kuralları hem de mesajları tek yerde toplar.
php artisan make:request StorePostRequest
class StorePostRequest extends FormRequest
{
public function authorize(): bool
{
return $this->user()->can('create', Post::class);
}
public function rules(): array
{
return [
'title' => ['required', 'string', 'max:255'],
'slug' => ['required', 'string', Rule::unique('posts')],
'body' => ['required', 'string'],
];
}
}
Ardından controller metodunda tip ipucu olarak bu sınıfı yazman yeterli. Laravel isteği otomatik doğrular, başarısızsa metoda hiç girmez:
public function store(StorePostRequest $request)
{
Post::create($request->validated());
}
authorize() metodunun false dönmesi 403 üretir; eğer yetki kontrolünü ayrı bir katmanda yapıyorsan bu metodu sadece return true; bırakabilirsin. Form Request yaklaşımı testleri de kolaylaştırır, çünkü kuralları izole olarak doğrulayabilirsin.
Özel kurallar ve closure kuralları
Hazır kuralların yetmediği yerlerde iki seçenek var. Tek seferlik bir kontrol için closure en hızlısıdır:
'slug' => [
'required',
function (string $attribute, mixed $value, Closure $fail) {
if (str_contains($value, ' ')) {
$fail("$attribute boşluk içeremez.");
}
},
],
Aynı kuralı birden çok yerde kullanacaksan, yeniden kullanılabilir bir kural sınıfı üretmek daha temizdir:
php artisan make:rule Uppercase
class Uppercase implements ValidationRule
{
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (strtoupper($value) !== $value) {
$fail('The :attribute must be uppercase.');
}
}
}
Kullanımı diğer kurallar gibidir: 'code' => ['required', new Uppercase]. Mesaj içindeki :attribute yer tutucusu otomatik olarak alan adıyla değiştirilir.
Hata mesajlarını yönetmek
Varsayılan mesajlar İngilizcedir ve geneldir. Türkçe ya da daha dostça mesajlar için Form Request içinde messages() ve attributes() metodlarını ezersin:
public function messages(): array
{
return [
'title.required' => 'Başlık alanı zorunludur.',
'title.max' => 'Başlık en fazla :max karakter olabilir.',
];
}
public function attributes(): array
{
return ['title' => 'başlık'];
}
Blade tarafında hataları göstermek için @error direktifi ve old() yardımcısı yeterlidir; old() kullanıcı verisinin form yeniden çizildiğinde kaybolmamasını sağlar:
<input name="title" value="{{ old('title') }}">
@error('title')
<span class="error">{{ $message }}</span>
@enderror
Çok dilli projelerde mesajları doğrudan kodun içine gömmek yerine lang/ klasöründeki çeviri dosyalarını kullanmak daha sürdürülebilirdir. Böylece aynı kural setini farklı dillerde tutarlı şekilde sunabilirsin.
Sık Sorulan Sorular
validate() ile Form Request arasındaki fark nedir?
İkisi de aynı motoru kullanır. validate() hızlı ve küçük formlar için idealdir; Form Request ise kuralları, yetkilendirmeyi ve mesajları ayrı bir sınıfta toplayarak controller'ı temiz tutar ve yeniden kullanımı kolaylaştırır.
API isteklerinde doğrulama hataları nasıl döner?
İstek Accept: application/json başlığı taşıyorsa Laravel yönlendirme yapmaz; 422 Unprocessable Entity kodu ile errors nesnesi içeren bir JSON yanıtı döndürür. Frontend bu yapıyı doğrudan işleyebilir.
Bir alanı yalnızca belirli koşulda doğrulayabilir miyim?
Evet. required_if gibi koşullu kuralları kullanabilir veya Form Request içinde sometimes() metoduyla çalışma zamanında dinamik kurallar ekleyebilirsin.
Doğrulama katmanı projenin güvenlik temelidir. Laravel validation mimarinizi sade ve test edilebilir hale getirmek ya da mevcut bir formdaki karmaşık kuralları toparlamak isterseniz benimle iletişime geçin.