PLAN Optimizasyon

Favorites N+1 Çözüm Planı

174 query → 1 query dönüşümü

26 Aralık 2025

❌ Mevcut Sorun

Blade Tarafı (N+1)

song-row.blade.php, song-card.blade.php, vb:

is_favorite: {{ $song->isFavoritedBy(auth()->id()) }}

Her şarkı için ayrı DB sorgusu → 174 query!

JavaScript Tarafı (✓ İyi)

favorites.js zaten optimize:

loadFavorites() → /api/favorites/list

Tek API call ile tüm favorileri çekiyor

📝 Basit Anlatım (Herkes İçin)

Ne yapacağız? Şu anda sayfa açıldığında her şarkı için "Bu favori mi?" diye ayrı ayrı soruyoruz. Bunun yerine sayfa açılırken tek seferde tüm favorileri çekip JavaScript'e vereceğiz.

Dinamik Güncellemeler:

  • Favori Ekleme: Kalbe tıkla → JS anında günceller → Sayfa yenilemeye gerek yok
  • Favori Çıkarma: Aynı şekilde anında güncellenir
  • Sonraki Sayfa: Yenilendiğinde güncel favoriler sunucudan gelir

Benzetme: Alışveriş listesi gibi düşün. Her ürüne baktığında "Bu listede mi?" diye cüzdana bakmak yerine, listeyi bir kere çıkarıp hepsini aynı anda kontrol ediyorsun.

🔧 Teknik Plan (6 Adım)

1

FavoriteService Oluştur

Modules/Favorite/app/Services/FavoriteService.php

Tek sorguda kullanıcının tüm favorilerini type bazlı gruplayarak döndürür:

getUserFavoriteIds($userId) → ['song' => [1,2,3], 'album' => [5,6], ...]
2

Layout'a Server Data Ekle

resources/views/themes/muzibu/layouts/app.blade.php

window.userFavorites = @json($favoriteIds ?? []);

Sayfa yüklendiğinde favoriler zaten JS'te hazır olacak

3

favorites.js - Server Data ile Init

public/themes/muzibu/js/player/features/favorites.js

// API call yapmak yerine server'dan gelen data'yı kullan
if (window.userFavorites) this.favorites = window.userFavorites;

API call kaldırılıyor → Ekstra network isteği yok

4

Blade Component'leri Güncelle

~15 component dosyası

❌ Eski (her biri query):

is_favorite: {{ $song->isFavoritedBy(auth()->id()) ? 'true' : 'false' }}

✅ Yeni (JS store kullan):

:is_favorite="$store.favorites.isFavorite('song', {{ $songId }})"
5

ViewComposer ile Global Data

app/Providers/AppServiceProvider.php veya ViewComposer

Tüm Muzibu view'larına $favoriteIds değişkeni otomatik inject edilir.

Controller'ları tek tek değiştirmek yerine merkezi çözüm.

6

Test & Karşılaştırma

  • • Telescope'da query sayısını kontrol et
  • • Favori ekleme/çıkarma test et
  • • Sayfa yenileme sonrası güncel durum kontrolü
  • • Guest kullanıcı (giriş yapmamış) testi

🔄 Dinamik Güncellemeler (Senin Sorun)

Senaryo: Kullanıcı yeni favori ekliyor

  1. 1

    Kullanıcı kalp ikonuna tıklar

    → $store.favorites.toggle('song', 123)

  2. 2

    JS hemen günceller (optimistic update)

    → Kalp kırmızı olur, toast gösterilir

  3. 3

    API call arka planda yapılır

    → POST /api/favorites/toggle

  4. 4

    DB'ye kaydedilir

    → favorites tablosuna INSERT

  5. Sayfa yenilenmeden anında yansır!

    → Tüm aynı şarkı kartları güncellenir (reactive)

Senaryo: Kullanıcı sayfayı yeniler

  1. 1. Sayfa yüklenirken server $favoriteIds hesaplar (1 query)
  2. 2. window.userFavorites olarak JS'e geçirilir
  3. 3. Alpine store bu data ile initialize olur
  4. 4. → Tüm favoriler güncel! API call gerekmez!

🚀 Beklenen Sonuç

174 → 1
Query Sayısı
~80ms
Kazanç
0
Extra API Call

📁 Değişecek Dosyalar

Yeni Oluşturulacak:

  • • Modules/Favorite/app/Services/FavoriteService.php

Güncellenecek:

  • • resources/views/themes/muzibu/layouts/app.blade.php
  • • public/themes/muzibu/js/player/features/favorites.js
  • • app/Providers/AppServiceProvider.php
  • • ~15 blade component (isFavoritedBy kaldırılacak)

⚠️ Onay Bekleniyor

Bu plan onaylanırsa uygulamaya geçeceğim. Değişiklikler: