Foruma hoş geldin 👋, Ziyaretçi

Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

Laravel Livewire bileşenlerinde N+1 sorgularını önlemek için `mount()` methodunda veriyi nasıl önceden yüklediğim

nexter

Üye
Katılım
14 Mart 2026
Mesajlar
6
Merhaba arkadaşlar, bugün başımı çok ağrıtan bir sorunu ve onun en temiz çözümünü paylaşmak istiyorum. Laravel Livewire ile bir proje geliştiriyordum ve bir liste sayfasında performansın aniden düştüğünü fark ettim. Sayfa açılırken sanki donuyordu! Debugbar'ı açtığımda gördüğüm manzara beni şoke etti: yüzlerce sorgu! Meğerse klasik N+1 sorgu problemi Livewire bileşenimde de baş göstermişti.

🔥 N+1 Problemi Nedir ve Livewire'da Neden Olur?

Livewire bileşenlerinde, genellikle verileri `render()` methodu içinde Blade'e paslarken veya bileşenin property'lerine erişirken ilişkili modelleri yüklemezsek bu sorunla karşılaşırız. Örneğin, bir `Post` modeli ve onun `comments` ilişkisi olsun. Eğer her postun yorumlarını ayrı ayrı sorgulamaya kalkarsak, 100 post için 1 (postları getir) + 100 (her post için yorumları getir) = 101 sorgu çalışır. İşte bu N+1'dir.

💡 Çözüm: Veriyi `mount()` Methodunda Önceden Yüklemek

Livewire'ın yaşam döngüsünde `mount()` methodu, bileşen ilk yüklendiğinde bir kere çalışır. Bu, veritabanı sorgularını yapmak için mükemmel bir yerdir. Amacımız, tüm gerekli ilişkileri burada, tek bir optimize edilmiş sorgu ile (`with()` kullanarak) yüklemek ve bu veriyi bileşenin property'sine atamak.

İşte benim kullandığım en temiz çözüm:

PHP:
<?php

namespace App\Http\Livewire;

use App\Models\Post;
use Livewire\Component;

class PostList extends Component
{
    public $posts;

    public function mount()
    {
        // N+1 SORUNU YARATAN KÖTÜ YÖNTEM:
        // $this->posts = Post::all();
        // Render içinde $post->comments dediğimiz her yerde yeni sorgu atılır.

        // ÇÖZÜM: İlişkileri `with()` ile önceden yükle
        $this->posts = Post::with(['comments.user', 'category'])->latest()->get();
    }

    public function render()
    {
        // Artık render methodunda ekstra sorgu yok.
        // Sadece yüklenmiş veriyi view'a iletiyoruz.
        return view('livewire.post-list');
    }
}

Burada `['comments.user', 'category']` diyerek, sadece yorumları değil, yorumların kullanıcı bilgisini (user) ve postun kategorisini de tek seferde yüklüyoruz. `latest()->get()` ile de en yeniden eskiye sıralayıp koleksiyonu alıyoruz.

⚙️ Blade Tarafında Nasıl Kullanılır?

Artık Blade şablonumuzda, `$posts` koleksiyonu üzerinde dönerken, her `$post->comments` veya `$post->category` çağrısı veritabanına yeni bir sorgu göndermeyecek. Çünkü tüm veri bellekte hazır bekliyor olacak.

HTML:
<div>
    @foreach($posts as $post)
        <div class="post-card">
            <h3>{{ $post->title }}</h3>
            <p>Kategori: {{ $post->category->name }}</p> <!-- Ek sorgu YOK -->
            <h4>Yorumlar:</h4>
            <ul>
                @foreach($post->comments as $comment)
                    <li>
                        {{ $comment->body }} - <strong>{{ $comment->user->name }}</strong> <!-- Ek sorgu YOK -->
                    </li>
                @endforeach
            </ul>
        </div>
    @endforeach
</div>

🎯 Neden `mount()`? `render()` İçinde Yapılamaz mı?

Yapılabilir, ancak `render()` methodu her bileşen yenilendiğinde (state değişikliği, etkileşim) çalışır. Eğer verileriniz değişmeyecekse (ilk yüklemedeki gibi), her seferinde aynı sorguyu çalıştırmak gereksiz olur. `mount()` ise sadece bileşen ilk oluşturulduğunda çalıştığı için daha performanslıdır. Tabii, bileşeninizdeki bir aksiyona bağlı olarak verilerin yeniden yüklenmesi gerekiyorsa, o zaman `render()` içinde veya özel bir methodda `with()` kullanmaya devam etmelisiniz.

Sonuç olarak, bu küçük dokunuşla sayfamın açılış süresi gözle görülür şekilde arttı. Debugbar'daki o korkunç sorgu listesi yerine, birkaç temiz ve optimize edilmiş sorgu görmek gerçekten huzur verici.

Siz Livewire projelerinizde N+1 sorunuyla nasıl başa çıkıyorsunuz? `mount()` dışında farklı bir yaklaşımınız var mı? Ya da belki Laravel'in lazy loading ve eager loading konusunda başka püf noktaları paylaşmak istersiniz? Yorumlarda buluşalım!
 

Tema özelleştirme sistemi

Bu menüden forum temasının bazı alanlarını kendinize özel olarak düzenleye bilirsiniz.

Zevkine göre renk kombinasyonunu belirle

Tam ekran yada dar ekran

Temanızın gövde büyüklüğünü sevkiniz, ihtiyacınıza göre dar yada geniş olarak kulana bilirsiniz.

Geri