Gereksinimler ve Ön Hazırlık
Bu projeyi başarıyla tamamlamak için sisteminizde Laravel 11 veya üzeri bir sürümün kurulu olması gerekmektedir. Ayrıca, veritabanı yönetimi için MySQL veya PostgreSQL kullanılması önerilir. Geliştirme ortamınızda Composer ve PHP 8.2+ sürümlerinin kurulu olduğundan emin olun.
- Laravel 11+ Framework
- PHP 8.2+
- Composer paket yöneticisi
- Temel veritabanı bilgisi (Migration ve Model ilişkileri)
Veritabanı Tasarımı: Tercihler Tablosu
Kullanıcı tercihlerini yönetmek için en esnek yöntem, "key-value" (anahtar-değer) yapısını kullanan bir tablo oluşturmaktır. Bu sayede, gelecekte yeni tercihler eklemek istediğinizde veritabanı şemasını değiştirmek zorunda kalmazsınız.
// Migration dosyası: create_user_preferences_table.php
public function up(): void
{
Schema::create('user_preferences', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->string('key'); // Örn: 'theme', 'notifications_enabled'
$table->text('value'); // Örn: 'dark', 'true'
$table->timestamps();
});
}
Yukarıdaki kod bloğunda, her tercihin bir kullanıcıya bağlı olduğu ve user_id üzerinden ilişkilendirildiği bir yapı kurduk. onDelete('cascade') kuralı, kullanıcı silindiğinde tercihlerinin de otomatik olarak temizlenmesini sağlar.
Eloquent İlişkilerini Tanımlama
Veritabanı yapısını kurduktan sonra, Laravel'in güçlü ORM'i olan Eloquent üzerinde bu ilişkiyi tanımlamalıyız. User modeline giderek tercihleri çekebileceğimiz bir ilişki metodu ekleyelim.
// User.php Modeli
public function preferences()
{
return $this->hasMany(UserPreference::class);
}
Bu ilişki sayesinde, herhangi bir kullanıcı nesnesi üzerinden $user->preferences diyerek tüm ayarlar listesine erişebiliriz. Bu yaklaşım, kodun okunabilirliğini ve yönetilebilirliğini ciddi oranda artırır.
Tercihleri Kaydetme ve Güncelleme Mantığı
Tercihleri yönetirken en yaygın hata, her tercih için ayrı bir satır oluşturup güncelleme yaparken zorlanmaktır. Bunun yerine "updateOrCreate" metodunu kullanmak, hem kod kalabalığını engeller hem de hatasız bir kayıt süreci sunar.
// PreferenceController.php
public function update(Request $request)
{
$validated = $request->validate([
'key' => 'required|string|max:255',
'value' => 'required|string',
]);
auth()->user()->preferences()->updateOrCreate(
['key' => $validated['key']],
['value' => $validated['value']]
);
return back()->with('success', 'Tercihleriniz güncellendi.');
}
Burada updateOrCreate metodu, eğer veritabanında belirtilen key mevcutsa onu günceller, değilse yeni bir kayıt oluşturur. Bu, kullanıcı tercihlerini dinamik tutmanın en pratik yoludur.
Kullanıcı Tercihlerini Uygulamada Kullanma
Tercihleri kaydettik, peki bunları uygulama içerisinde nasıl çağıracağız? Her seferinde veritabanına sorgu atmak yerine, tercihler yüklendiğinde bunları bir collection olarak belleğe almak performans açısından daha verimlidir.
// AppServiceProvider.php veya View Composer
View::composer('*', function ($view) {
if (auth()->check()) {
$preferences = auth()->user()->preferences->pluck('value', 'key');
$view->with('userPrefs', $preferences);
}
});
Bu kod bloğu, uygulamanın her sayfasında $userPrefs['theme'] şeklinde tercihlere erişmenizi sağlar. pluck metodu, verileri ['key' => 'value'] formatında bir diziye dönüştürerek erişimi kolaylaştırır.
Karşılaştırma: Tercih Yönetim Yöntemleri
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Key-Value Tablosu | Esnek, dinamik, ölçeklenebilir | Karmaşık sorgularda yavaş olabilir |
| JSON Sütunu (Users Tablosu) | Hızlı, tek satırda yönetim | Veri büyüdükçe filtreleme zorlaşır |
Güvenlik ve Performans İpuçları
Kritik Uyarı: Kullanıcıdan gelen tercih verilerini mutlaka
validatemetodundan geçirin. SQL Injection riskini önlemek için Eloquent'in sunduğu korumalı metodları (updateOrCreate gibi) kullanın. Ayrıca, çok sık erişilen tercihler için Redis veya Memcached gibi bir önbellekleme (caching) mekanizması kullanarak veritabanı yükünü azaltın.
Güvenlik konusunda dikkat edilmesi gereken bir diğer nokta, kullanıcıların sadece kendi tercihlerini değiştirebildiğinden emin olmaktır. Bunun için Laravel Policy veya Form Request sınıflarını mutlaka kullanmalısınız.
Sıkça Sorulan Sorular
Tercihleri veritabanı yerine JSON dosyasında tutabilir miyim?
Küçük projeler için mümkün olsa da, ölçeklenebilirlik ve kullanıcı bazlı yönetim için veritabanı kullanımı standarttır.
Çok fazla tercih eklersem sistem yavaşlar mı?
İndeksleme (index) kullanarak key sütununu hızlandırabilir ve tercihleri bir kez çekip bellekte tutarak (caching) performansı koruyabilirsiniz.
Kullanıcı tercihlerini varsayılan değerlerle nasıl birleştiririm?
collect($defaultSettings)->merge($userPreferences) fonksiyonunu kullanarak eksik olan tercihleri varsayılan değerlerle tamamlayabilirsiniz.
Tercihleri bir API üzerinden yönetebilir miyim?
Evet, aynı Controller mantığını bir API Resource kullanarak JSON yanıtı dönecek şekilde kolayca uyarlayabilirsiniz.
Hangi durumlarda JSON sütunu daha avantajlıdır?
Eğer tercihleriniz çok az sayıdaysa ve kullanıcı tablosuyla doğrudan ilişkiliyse, users tablosuna eklenecek bir settings (json) sütunu daha hızlı sonuç verebilir.
SettingsService ile Mimariyi Modülerleştirme
Uygulamanız büyüdükçe, tercihleri doğrudan Controller içerisinde yönetmek kod tekrarına ve bakım zorluklarına yol açar. Bu karmaşıklığı aşmak için tüm tercih işlemlerini tek bir SettingsService sınıfında toplamak, iş mantığınızı (business logic) izole etmenizi sağlar.
Aşağıdaki örnekte, tercihleri hem okuyan hem de önbelleğe (cache) alarak performans kazandıran modüler bir yapı oluşturuyoruz:
namespace App\Services;
use App\Models\UserPreference;
use Illuminate\Support\Facades\Cache;
class SettingsService
{
public function get(int $userId, string $key, $default = null)
{
return Cache::remember("user_{$userId}_pref_{$key}", 3600, function () use ($userId, $key, $default) {
$pref = UserPreference::where('user_id', $userId)->where('key', $key)->first();
return $pref ? $pref->value : $default;
});
}
public function set(int $userId, string $key, $value): void
{
UserPreference::updateOrCreate(
['user_id' => $userId, 'key' => $key],
['value' => $value]
);
Cache::forget("user_{$userId}_pref_{$key}");
}
}
Tercih Yönetiminde Hata Ayıklama ve Loglama
Dinamik sistemlerde en büyük sorun, kullanıcıların beklenmedik değerler girmesi veya veritabanındaki veri tipinin uygulama tarafından yanlış yorumlanmasıdır. Bu tür hataları tespit etmek için Laravel'in Logging sistemini tercih yönetimi süreçlerine entegre etmelisiniz.
Tip Güvenliği ve Doğrulama
Kullanıcı tercihlerini kaydederken mutlaka bir doğrulama (validation) katmanı kullanın. Örneğin, "tema" tercihi sadece light veya dark değerlerini alabiliyorsa, bunu şu şekilde kontrol edebilirsiniz:
public function updateTheme(Request $request)
{
$validated = $request->validate([
'theme' => 'required|in:light,dark'
]);
try {
app(SettingsService::class)->set(auth()->id(), 'theme', $validated['theme']);
} catch (\Exception $e) {
Log::error("Tercih güncellenemedi: " . $e->getMessage());
return back()->withErrors('Tercihler kaydedilirken bir hata oluştu.');
}
}
Performans İçin İleri İpuçları
- Eager Loading: Eğer bir sayfada birden fazla tercihi aynı anda kullanıyorsanız,
UserPreferencemodellerini$user->preferencesilişkisi üzerindenwith()kullanarak çekin. - Database Indexing:
user_idvekeysütunlarına mutlaka birleşik bir index (composite index) ekleyin. Bu, sorgu hızını önemli ölçüde artıracaktır. - Cache Tagging: Eğer Redis kullanıyorsanız, tüm kullanıcı tercihlerini bir etiket (tag) altında toplayarak, kullanıcı oturumu kapandığında veya ayarlar sıfırlandığında tüm cache'i tek seferde temizleyebilirsiniz.
Profesyonel Not: Veritabanı sorgularını azaltmak için, giriş (login) anında tüm kullanıcı tercihlerini bir array olarak oturum (session) içerisine yüklemek, sayfa yüklenme sürelerini milisaniyeler seviyesine indirecektir.
Sonuç
Laravel ile dinamik bir kullanıcı tercihleri yönetim paneli oluşturmak, uygulamanızın profesyonel ve kullanıcı odaklı hissettirmesini sağlar. Bu rehberde öğrendiğiniz key-value yapısı, veritabanı ilişkileri ve view composer kullanımı, Laravel projelerinizde esnek bir ayar sistemi kurmanıza olanak tanır. Bir sonraki adım olarak, bu tercihleri bir "SettingsService" sınıfı içerisine alarak kodunuzu daha modüler hale getirmeyi deneyebilirsiniz.
Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce mutlaka birim testlerinizi (unit tests) yapın ve gerekli güvenlik taramalarını gerçekleştirin.


Yorumlar (0)
Yorum Yaz