“Bu alan yalnızca bazen zorunludur”
“Bu alan yalnızca bazen zorunludur”
Her doğrulama kuralı basit başlar. required, email, min:8, tamam. Sonra Product Owner gelir ve sihirli cümlesini söyler:
“Ah, ama CNPJ yalnızca kişi tüzelse zorunludur.”
Ve sadelik gider. Aniden, doğrulamanız başka bir alana bağımlı hale gelir ve herkesin yaptığı gibi ilk defa bir if kullanırsınız, bir kısmı doğrularsınız, sonra başka bir kısmı doğrularsınız ve store() metodu bir dal budak haline gelir.
Bunu yaşadınız mı? İyi haber şu ki, Laravel’in neredeyse her tür “bağımlılık” için bir aracı var. Tümünü elle çözmeye çalışmamayı öğrenmelisiniz.
Problem: Kontrolcüdaki parçalı doğrulama
Problem: Kontrolcüdaki parçalı doğrulama
Naif yaklaşım, gelen verilere bağlı olarak parçalı doğrulamaktır:
public function store(Request $request)
{
$regras = [
'tipo' => 'required|in:pf,pj',
'nome' => 'required|string',
];
// burada karışıklık başlar
if ($request->tipo === 'pj') {
$regras['cnpj'] = 'required|string|size:14';
} else {
$regras['cpf'] = 'required|string|size:11';
}
if ($request->quer_newsletter) {
$regras['email'] = 'required|email';
}
$request->validate($regras);
// ...
}
Çalışıyor mu? Evet. Ama ne olup bittiğine dikkat edin: iş mantığınız artık manuel bir dizi oluşturma ile dağılmış durumda, kontrolcü doğrulamaya fazla hakim ve bunu test etmek tanrının cehennemi. Her yeni if, yanlış gidebilecek yeni bir dal budak oluşturur.
Çözüm 1: required_if ve diğerleri
Çözüm 1:
required_if ve diğerleriAlanlar arasındaki basit bağımlılıklar için Laravel’in zaten mevcut kuralları var. Çoğu zaman bunun için if kullanmanıza gerek yok:
public function rules(): array
{
return [
'tipo' => 'required|in:pf,pj',
'cnpj' => 'required_if:tipo,pj|nullable|size:14',
'cpf' => 'required_if:tipo,pf|nullable|size:11',
'email' => 'required_if:quer_newsletter,true|email',
];
}
Bunun gibi birçok kural var: required_unless, required_with, required_without, required_with_all, exclude_if, prohibited_if… Önce bir if yazmadan önce arkanızda zaten var mı diye kontrol etmek her zaman iyi bir fikir. Çoğu durumda vardır.
Çözüm 2: Rule::when ile kural içindeki koşul
Çözüm 2:
Rule::when ile kural içindeki koşulKoşulun “bir alan diğer bir alana bağımlıdır” şeklinde değil, bir bağlama (giriş yapan kullanıcı, bir plan, bir özellik bayrağı) dayanıyorsa, Rule::when bunu kendi dizisi içinde açıklayıcı hale getirir:
use Illuminate\Validation\Rule;
public function rules(): array
{
return [
'titulo' => 'required|string',
// yalnızca admin ise zorunlu ve benzersiz olarak doğrula
'slug' => Rule::when(
$this->user()->isAdmin(),
['required', 'unique:posts,slug'],
['nullable'] // değilse, opsiyonel
),
];
}
Yukarıdan aşağıya aktiviteyi okudunuz ve tüm kuralı anlamış oldunuz, üç metot yukarıya kadar bir if aramak zorunda kalmadınız.
Çözüm 3: sometimes() ile diziye sığmayan mantık
Çözüm 3:
sometimes() ile diziye sığmayan mantıkKoşul gerçekten karmaşık olduğunda ve “indirim yalnızca gelirse ve sipariş 500 lirayı geçirirse geçerlidir” gibi durumlara girdiğimizde, sometimes() Validator’ın işidir ve en iyi withValidator() içinde kullanılmalıdır:
use Illuminate\Validation\Validator;
public function withValidator(Validator $validator): void
{
$validator->sometimes('desconto', 'numeric|max:50', function ($input) {
return $input->cupom && $input->total > 500;
});
}
desconto kuralı yalnızca o closure true dönerse uygulanır. Tüm karmaşık mantık, tek bir yerde, adlandırılabilir, test edilebilir ve ana akıştan uzakta kalır.
Pratikte nasıl kullanılır
Pratikte nasıl kullanılır
Dizi/kollection doğrulaması — N tekrarı olan form (bir sepet, bir davetli listesi) için .* kullanın:
public function rules(): array
{
return [
'itens' => 'required|array|min:1',
'itens.*.produto_id' => 'required|exists:produtos,id',
'itens.*.quantidade' => 'required|integer|min:1',
];
}
Bir kural, dizi içindeki N elemanı doğrular. Manuel olarak foreach ile doğrulama yok.
Koşula göre özelleştirilmiş mesaj — messages() ile Form Request’te birleştirilip kullanıcıya “Tüzel kişi için CNPJ belirtin” gibi bir mesaj verecek şekilde kullanılır.
Kandırmaca: nullable ve kuralın olmaması
Kandırmaca:
nullable ve kuralın olmamasıBirçok insan buradan düşer. required_if kullanıyorsanız, çoğu zaman nullable ile birleştirmeniz gerekir. Eğer bu sağlanmazsa, alan boş gelirse (ama istek içinde mevcutsa), diğer kurallar gibi size:14 veya email hala boş olan dizeyi doğrulamaya çalışacak ve şikayet edecek.
// ❌ Eğer cnpj='' bir PF geldiğinde, size:14 sorun çıkarır
'cnpj' => 'required_if:tipo,pj|size:14',
// ✅ Boş olması, zorunlu olmadığında izin verir
'cnpj' => 'required_if:tipo,pj|nullable|size:14',
nullable “boş/nul olabilir ve bu durumda diğer kuralları görmezden gel” anlamına gelir. required_if‘nin doğal eşleşmesidir. Bunu tutun, bir saatlik hata ayıklama tasarrufu sağlar.
Bonus: Şimdi ne olacak?
Bonus: Şimdi ne olacak?
Projenizdeki en fazla if ile dolu olan Form Request’i (veya kontrolcüyü) açın ve bu egzersizi yapın: kural dizisi oluşturmak için var olan her if büyük olasılıkla mevcut ve karşılanacak bir required_if, Rule::when veya sometimes ile değiştirilebilir.
Henüz doğrulamayı doğrudan kontrolcüde $request->validate() ile yapıyorsanız, tümünü bir Form Request’e taşımak için bir teşvik. Tüm bu olanaklar, orada çok daha düzenli hale gelir.
Sekmeyi kapatmadan önce
Sekmeyi kapatmadan önce
Altın kural: Eğer doğrulama dizisini if ile oluşturuyorsanız, Laravel bunun için muhtemelen zaten dekleratif bir yol sunuyor. Doğrulama belgelerine bakmayı unutmayın. Listeye göz atın; neredeyse hiç kimsenin kullanmadığı yaklaşık 20 kural var ve bunlar el ile yapmaya çalıştığımız durumları çözüyor.
En çok hangi koşullu doğrulama kuralını kullanıyorsunuz? Ya da hangi karmaşık durumu nasıl çözeceğinizi bilmediğiniz bir durum var mı? Yorumlarda paylaşın, birlikte inceleyelim. 👇
Kaynak: Orijinal Makale
- “Bu alan yalnızca bazen zorunludur”
- Problem: Kontrolcüdaki parçalı doğrulama
- Çözüm 1: required_if ve diğerleri
- Çözüm 2: Rule::when ile kural içindeki koşul
- Çözüm 3: sometimes() ile diziye sığmayan mantık
- Pratikte nasıl kullanılır
- Kandırmaca: nullable ve kuralın olmaması
- Bonus: Şimdi ne olacak?
- Sekmeyi kapatmadan önce


