Laravel geliştiricileri kısayolları sever. Daha sıkı bir sözdizimi ve daha az boilerplate ile daha az satır yazmak tatmin edici olabilir. Ancak gerçeği söylemek gerekirse, kod daha kısa olduğu için daha iyi olmadığını unutmayalım. Bir takımda çalışırken ve gereksinimler sürekli değişirken, açık ve anlaşılır kod her zaman kazanan olur.
Son zamanlarda, daha temiz bir kod için whereHas() yerine whereRelation() kullanmamız gerektiğini öneren bir Laravel ipucu ile karşılaştım. Örneğin şu şekilde:
// ÖNCE
$users = User::whereHas('profile', function ($query) {
$query->where('is_verified', false);
})->get();
// SONRA
$users = User::whereRelation('profile', 'is_verified', false)->get();
Orijinal paylaşımı tam olarak incelemek isterseniz buradan kontrol edebilirsiniz.
Bu tavsiyeye şu şekilde yaklaşıyorum.
Tavsiye yanlış değil, ancak whereRelation()‘ı daha iyi bir alternatif olarak sunmak yanıltıcı. Bu sadece sembolik bir şeker. Gerçek bir projede, o yüzeysel “temizlik” geri tepebilir.
Gerçek Sorun: Okunabilirlik ve Niyet
Gerçek Sorun: Okunabilirlik ve Niyet
Benim üretimde kullandığım yöntem:
$users = User::query()
->whereHas('profile', fn(Builder $query) => $query->where('is_verified', false))
->get();
Neden bu yöntem daha iyi? Çünkü niyeti açık bir şekilde iletir.
whereHas() olduğunda, hemen anlaşılıyor:
- İlişkinin filtrelenmesi yapılıyor
- Mantık o ilişkinin kapsamı içinde bulunuyor
- Daha fazla koşul doğal bir şekilde eklenebilir
Not: Burada ok yönlü fonksiyonlar kullanıyorum, ama bu ayrı bir iyileştirme; her iki yöntemle de kullanabilirsiniz. Ana ayrım, kullanılan yöntemdir.
whereRelation()’ın Zayıf Yanları
whereRelation()’ın Zayıf Yanları
whereRelation()‘in sorunu, gerçekte ne olduğunu gizlemesidir. Sadece basit bir sütun filtresi gibi görünürken, arka planda ilişkili bir tabloya karşı bir alt sorgu çalıştırır.
->whereRelation('profile', 'is_verified', false)->get();
Bu durum, doğrudan users tablosundaki bir sütunun filtrelenmesi gibi okunuyor. Bu yanıltıcıdır.
Birden fazla koşula ihtiyaç duyduğunuzda, whereHas() ile eklemeleri kolayca yapabilirsiniz:
->whereHas('profile', fn(Builder $query) => $query
->where('is_verified', false)
->whereNotNull('phone')
->where('age', '>', 18)
)
whereRelation() ile bu durum karmaşık veya imkansız hale gelir. Birkaç zincirleme çağrı yapmanız veya tekrar whereHas()‘a dönmeniz gerekecek.
whereRelation() Ne Zaman Uygundur
whereRelation() Ne Zaman Uygundur
whereRelation() kullanmak konusunda tamamen karşı değilim. Hızlı idare raporları, geçici scriptler ve asla daha karmaşık olmayacak küçük filtreler gibi durumlar için uygun.
Örneğin:
User::query()->whereRelation('profile', 'is_verified', true)->count();
Bu kadar basit. Ancak mantığınız biraz daha karmaşık hale geldiğinde, hemen whereHas()‘a yönelin. Bu, daha net ve gelecekteki kendiniz veya takım arkadaşlarınız için kafa karıştırıcı olmayacaktır.
Performans Soruları
Performans Soruları
Pek çok geliştirici whereHas()‘dan kaçınıyor çünkü birisi bunun yavaş olduğunu söyledi. Bu tamamen farklı bir tartışma ve genellikle sorun eksik indekslerdendir, ya da sorgu oluşturucusuna geçme zamanıdır.
Eğer profiles.is_verified üzerinde filtreleme yapıyorsanız ve bir indeks yoksa, hem whereHas() hem de whereRelation() yavaş olacaktır; neredeyse aynı SQL’i üretirler.
Peki pratik bir sorun: Bir projeye katıldığınızda “kullanıcılar uç noktası yavaş” gibi bir bilet buldunuz. Ne yaparsınız? Kod tabanında ilişki sorguları arayıp uygun indekslerin var olup olmadığını kontrol edersiniz.
whereHas ararsınız… ve hiçbir şey bulamazsınız. Görünüşe göre önceki geliştirici her yerde whereRelation() kullanmış. Şimdi de görsel olarak ilişki filtreleri gibi görünmeyen method çağrıları arasında avlanıyorsunuz. whereHas() kolayca aranabilir ve belirgindir. whereRelation() ise gözden kaçabilir.
Tutarlılık Sorunu
Tutarlılık Sorunu
Gerçek kod tabanlarında olan durum şu:
Basit bir başlangıç yaparsınız. Belki whereRelation()‘a yönelirsiniz:
User::query()->whereRelation('profile', 'is_verified', true)->get();
Ama iş mantığı her zaman değişir. Aniden ikinci bir koşula ihtiyacınız olur ve whereHas()‘a geçersiniz:
User::query()->whereHas('profile', fn(Builder $query) => $query
->where(, true)
->whereNotNull()
)->get();
Artık kod tabanınız hem whereRelation() hem de whereHas() gibi iki farklı desene sahip. Yeni gelenler hangisini kullanacağını bilmiyor. Kod gözden geçirmeleri tutarsız hale geliyor. Bir dosyada whereRelation(), diğerinde whereHas() gördüğünüzde, bunun için gerçek bir neden yok. Ekipler, bir varsayılan üzerinde hemfikir olmalı ve yalnızca bir sebep ile farklılık göstermelidir.
Gün başından itibaren whereHas() kullandıysanız, bu durum asla yaşanmaz. Tek bir stil, her yerde tutarlı ve kodunuz gereksinimlerin karmaşıklaştığında hazır olur.
Laravel İç İşleyişi: Burada Sihir Yok
Laravel İç İşleyişi: Burada Sihir Yok
Gerçek olalım, whereRelation() aslında whereHas() etrafında bir sargıdır. Daha akıllı, daha temiz, daha verimli veya daha hızlı değildir. Sadece bir closure yazmaktan sizi kurtarır. Bunu kaynak kodunda kontrol edebilirsiniz.
Bu basit durumlar için uygun. Ancak gerçek dünyada uygulamalar, birden fazla koşul, sürdürülebilirlik kaygıları veya gelecekteki büyüme şansı olduğunda whereHas()‘ın seçilmesi modası geçmiş değil, kodunuzun ne yaptığını daha samimi bir şekilde ifade etme gereğidir.
Kuralım
Kuralım
- Bir koşul, eğer büyüme şansı yoksa, hızlı bir script? Gidin
whereRelation()ile. - Her şey önemli: iş mantığı, takım projeleri, geri döneceğiniz kod kullanın
whereHas().
Birkaç tuş darbesi tasarrufu yapmaya çalışmayın. Kodu okuyan bir sonraki geliştirici (ya da kendiniz altı ay sonra) için yazın. whereRelation() hoş bir kısayol, ama kolaylığı açıklıkla karıştırmayın. Çoğu gerçek senaryoda, temiz sözdizimiyle whereHas() okunabilirlik, ölçeklenebilirlik ve niyet açısından kazanır.
Yazar Notu
Yazar Notu
Burada olduğunuz için teşekkürler!
Beni dev.to, linkedin üzerinden bulabilirsiniz veya çalışmalarımı github‘da inceleyebilirsiniz.
Gerçek hayatta Laravel notları.
Kaynak: Orijinal Makale


