Dashboard'da JSON görüntüleme ve Favoriler sayfası UX sorunları çözüldü
Muzibu müzik platformunda iki önemli sorun vardı:
Şarkı, albüm, sanatçı gibi içeriklerin isimleri ekranda düzgün görünmüyordu.
Mesela "Faded" yerine {"tr":"Faded"} şeklinde garip kodlar görünüyordu.
Sistem çok dilli olduğu için veriler JSON formatında saklanıyordu, ama bu verileri otomatik olarak düzgün metne çevirecek sistem eksikti.
Favoriler sayfasında şarkılar, albümler, playlistler, türler, sektörler, radyolar hepsi birbirine karışmıştı. Kullanıcı favorilerine baktığında hangisinin şarkı, hangisinin albüm olduğunu anlamakta zorlanıyordu.
Ayrıca tüm içerikler aynı görsel tasarımla gösteriliyordu, bu da karışıklığı artırıyordu.
Translatable fields (title, slug, description, lyrics) database'de JSON formatında saklanıyordu:
{"tr":"Faded", "en":"Faded"}
Ancak Eloquent model'ler bu JSON'ı otomatik olarak parse etmiyordu. Accessor pattern denendiğinde infinite loop oluştu.
HasTranslations trait'inde
getAttribute() method override edildi:
// app/Traits/HasTranslations.php:133-166
public function getAttribute($key)
{
// Eğer translatable field ise, önce JSON parse et
if ($this->isTranslatable($key)) {
// Raw value al (attributes array'inden direkt)
$value = $this->getAttributeFromArray($key);
// JSON parse ve locale'ye göre döndür
if (is_string($value)) {
try {
$decoded = json_decode($value, true);
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
$locale = app()->getLocale() ?: 'tr';
// Mevcut locale'deki değer varsa döndür
if (isset($decoded[$locale]) && !empty($decoded[$locale])) {
return $decoded[$locale];
}
// Fallback
return $this->getFallbackTranslation($decoded, $locale);
}
} catch (\Exception $e) {
return $value;
}
}
return $value;
}
// Normal field, parent'a devret (relationlar vs.)
return parent::getAttribute($key);
}
app/Traits/HasTranslations.php - getAttribute() overrideModules/Muzibu/app/Models/Song.php - Accessor'lar kaldırıldıModules/Muzibu/app/Models/Album.php - Accessor'lar kaldırıldıModules/Muzibu/app/Models/Artist.php - Accessor'lar kaldırıldıModules/Muzibu/app/Models/Playlist.php - Accessor'lar kaldırıldıModules/Muzibu/app/Models/Genre.php - Accessor'lar kaldırıldıModules/Muzibu/app/Models/Sector.php - Accessor'lar kaldırıldıModules/Muzibu/app/Models/Radio.php - Accessor'lar kaldırıldı
Model accessor'ları getAttribute() çağırırsa infinite loop oluşur.
Çözüm: Trait seviyesinde getAttribute() override et ve
getAttributeFromArray() kullan.
Her content type için ayrı tab:
@if(($counts['songs'] ?? 0) > 0)
<a href="{{ route('muzibu.favorites', ['type' => 'songs']) }}">
Şarkılar <span>({{ $counts['songs'] }})</span>
</a>
@endif
Her tip kendi component'ini kullanıyor:
<x-muzibu.song-list-item> (list)<x-muzibu.album-card> (grid)<x-muzibu.playlist-card> (grid)<x-muzibu.genre-card> (grid)<x-muzibu.sector-card> (grid)<x-muzibu.radio-card> (grid)Kullanıcı type belirtmezse ilk dolu type'a yönlendir:
// FavoritesController.php:38-48
$type = $request->get('type');
if (!$type) {
foreach ($counts as $key => $count) {
if ($count > 0) {
return redirect()->route('muzibu.favorites', ['type' => $key]);
}
}
// Hiç favori yoksa songs'a yönlendir
$type = 'songs';
}
Modules/Muzibu/app/Http/Controllers/Front/FavoritesController.phpresources/views/themes/muzibu/favorites/index.blade.phpresources/views/themes/muzibu/dashboard.blade.phpresources/views/themes/muzibu/components/song-list-item.blade.phpJSON parsing logic'i trait seviyesinde tutularak tüm modellere otomatik olarak uygulanıyor. Her model için ayrı kod yazmaya gerek kalmadı.
Her content type kendi Blade component'ini kullanıyor. Bu sayede:
Boş tab'ler gösterilmiyor. Bu sayede kullanıcı sadece dolu kategorileri görüyor ve karışıklık önleniyor.
Type parametresi yoksa sistem otomatik olarak ilk dolu category'ye yönlendiriyor. Kullanıcı her zaman anlamlı bir sayfa görüyor.
with('favoritable') ile N+1 problem yok
Translatable field'lar için otomatik JSON parsing eklendi
Song, Album, Artist, Playlist, Genre, Sector, Radio - infinite loop sorunu çözüldü
Count calculation, auto-redirect logic, all content types support eklendi
Tab-based categorization, component-based display, conditional rendering
Song-list-item component kullanarak list format'a çevrildi
View, config, route, response cache'leri temizlendi
Tüm değiştirilen dosyalar için tuufi.com_:psaserv ownership ve doğru permissions
Tüm sistemde JSON display sorunu kalıcı olarak çözüldü. HasTranslations trait kullanan tüm modeller otomatik olarak düzgün metin gösteriyor.
Kullanıcılar artık favorilerini kategorize şekilde görebiliyor. Her content type kendi component'i ve görsel tasarımıyla görünüyor.
Component-based architecture ve trait-level solution ile temiz, maintainable kod yapısı oluşturuldu.
Eager loading ve component caching ile optimal performans sağlandı. N+1 query problem yok.
Claude AI tarafından hazırlandı | Muzibu Platform | 24 Aralık 2025