Laravel İle Dinamik Bir Ürün Karşılaştırma Modülü Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Bu projeye başlamadan önce sisteminizde Laravel'in çalışması için gereken temel ortamın kurulu olduğundan emin olmalısınız. Aşağıdaki araçların yüklü olması gerekmektedir:

  • PHP 8.2 veya üzeri
  • Composer paket yöneticisi
  • Laravel 11.x kurulu bir proje
  • Veritabanı olarak MySQL veya PostgreSQL

Projenizi hazırladıktan sonra, ürünleri tutacağımız bir products tablosunun ve bu ürünlerin özelliklerini içeren bir yapının hazır olması gerekir. Eğer veritabanınız hazır değilse, php artisan make:migration create_products_table komutu ile tablonuzu oluşturarak işe başlayabilirsiniz.

Adım 1: Ürün Karşılaştırma Mantığını Session Üzerinde Kurma

Karşılaştırma modülünün en kritik noktası, kullanıcının seçtiği ürünleri veritabanına kalıcı olarak yazmadan, oturum süresince saklamaktır. Bu, performansı artırır ve veritabanı yükünü hafifletir. Laravel'in session yardımcı fonksiyonu bu iş için idealdir.

// App\Http\Controllers\CompareController.php
public function add(Request $request, $productId)
{
    $compareList = session()->get('compare_list', []);

    if (!in_array($productId, $compareList) && count($compareList) < 4) {
        $compareList[] = $productId;
        session()->put('compare_list', $compareList);
    }

    return response()->json(['success' => true, 'count' => count($compareList)]);
}

Yukarıdaki kod bloğunda, kullanıcının oturumunda compare_list adında bir dizi oluşturuyoruz. Güvenlik ve kullanıcı deneyimi açısından aynı anda en fazla 4 ürünün karşılaştırılmasına izin veriyoruz. session()->put() metodu ile bu veriyi sunucu tarafında güvenli bir şekilde saklıyoruz.

Adım 2: Karşılaştırma Sayfası İçin Veri Hazırlama

Kullanıcı karşılaştırma sayfasına geldiğinde, session içindeki ID'leri kullanarak veritabanından ilgili ürün bilgilerini çekmemiz gerekir. Burada whereIn metodunu kullanarak tek bir sorgu ile tüm ürünleri getiriyoruz.

// App\Http\Controllers\CompareController.php
public function index()
{
    $productIds = session()->get('compare_list', []);
    $products = Product::whereIn('id', $productIds)->get();

    return view('compare.index', compact('products'));
}

Bu yöntem, her ürün için ayrı sorgu atmak yerine (N+1 problemi), tüm ürünleri tek seferde veritabanından çekerek uygulamanızın hızını optimize eder.

Adım 3: Blade Şablonu ile Dinamik Karşılaştırma Tablosu

Verileri Blade şablonuna gönderdikten sonra, bu verileri şık ve okunabilir bir tablo yapısında göstermeliyiz. Aşağıdaki örnekte, ürünlerin özelliklerini dinamik olarak döngüye alıyoruz.


            @foreach($products as $product)
                
            @endforeach
        
            @foreach($products as $product)
                
            @endforeach
        
Özellik{{ $product->name }}
Fiyat{{ number_format($product->price, 2) }} TL

Bu yapı, ürün sayısı arttıkça tablonun otomatik olarak genişlemesini sağlar. number_format fonksiyonu ile fiyatları yerel para birimi formatına uygun hale getiriyoruz.

Karşılaştırma Yöntemleri Karşılaştırması

Yöntem Avantajı Dezavantajı
Session (Oturum) Hızlı, veritabanı yükü yok Kullanıcı çıkış yapınca silinir
Veritabanı (Tablo) Kalıcı, cihazlar arası senkron Daha fazla veritabanı sorgusu
Cookie (Çerez) Tarayıcı kapansa da kalır Boyut kısıtlaması (4KB)

Adım 4: Güvenlik ve Hata Yönetimi

Kullanıcıdan gelen ID'lerin doğrulanması (validation) çok önemlidir. Kullanıcının olmayan bir ID'yi session'a eklemesini engellemek için exists kuralını kullanmalısınız.

Güvenlik Uyarısı: Session verilerini manipüle etmeye çalışan kullanıcılara karşı her zaman veritabanı sorgularınızda exists kontrolü yapın. Ayrıca, kullanıcı girdilerini mutlaka temizleyin (sanitize) ve XSS saldırılarına karşı Blade'in {{ }} sözdizimini kullanın.

$request->validate([
    'product_id' => 'required|exists:products,id'
]);

Bu doğrulama, geçersiz verilerin sisteme girmesini engeller ve veritabanı bütünlüğünü korur.

Adım 5: JavaScript ile Asenkron Ekleme

Kullanıcının sayfayı yenilemeden ürün eklemesi için fetch API veya Axios kullanabilirsiniz. Bu, modern bir kullanıcı deneyimi için zorunludur.

function addToCompare(productId) {
    fetch('/compare/add/' + productId, {
        method: 'POST',
        headers: {'X-CSRF-TOKEN': '{{ csrf_token() }}'}
    }).then(response => response.json())
      .then(data => alert('Ürün eklendi! Toplam: ' + data.count));
}

CSRF token kullanımı Laravel'de form ve AJAX isteklerinin güvenliği için olmazsa olmazdır. X-CSRF-TOKEN başlığını eklemeyi unutmamalısınız.

Sıkça Sorulan Sorular

Karşılaştırma listesini veritabanında mı tutmalıyım?

Eğer kullanıcının farklı cihazlarda (mobil, masaüstü) aynı listeyi görmesini istiyorsanız veritabanında tutmalısınız. Ancak sadece geçici bir inceleme için oturum (session) yeterlidir.

Aynı anda kaç ürün karşılaştırılmalı?

Kullanıcı deneyimi açısından 3 veya 4 ürün idealdir. Daha fazlası ekranın okunabilirliğini bozar.

Ürün silme işlemini nasıl yaparım?

Session dizisinden array_diff veya unset kullanarak belirli bir ID'yi kolayca kaldırabilirsiniz.

Bu modül SEO'yu etkiler mi?

Karşılaştırma sayfalarınızın "noindex" olarak işaretlenmesi, kopya içerik (duplicate content) sorunlarını önlemek adına önerilir.

Mobil cihazlarda tablo nasıl görünür?

Tablonuzu CSS overflow-x: auto özelliği ile sarmalayarak mobil cihazlarda yatay kaydırılabilir hale getirebilirsiniz.

İleri Seviye Optimizasyon: Karşılaştırma Modülünde Performans İpuçları

Ürün karşılaştırma modülünüz büyüdükçe ve ürün sayısı arttıkça, veritabanı sorgularının verimliliği kritik bir hale gelir. Özellikle whereIn sorguları kullanılırken, Laravel'in eager loading (istekli yükleme) özelliğini kullanmak, N+1 probleminden kaçınmanızı sağlar. Karşılaştırma listesindeki ürünleri çekerken, ilişkili tabloları (kategori, marka, teknik özellikler) tek bir sorguda almak performansı ciddi oranda artıracaktır.

Aşağıdaki örnekte, session'daki ID'leri kullanarak verileri nasıl optimize bir şekilde çekeceğinizi görebilirsiniz:

// ProductController.php içerisinde optimize edilmiş sorgu
public function compare(Request $request)
{
    $productIds = session()->get('comparison_list', []);

    // with() metodu ile ilişkili verileri tek seferde çekiyoruz
    $products = Product::whereIn('id', $productIds)
        ->with(['category', 'brand', 'specifications'])
        ->get();

    return view('products.compare', compact('products'));
}

Ayrıca, ürünlerin teknik özelliklerini (specifications) JSON formatında saklıyorsanız, veritabanı seviyesinde indeksleme yapmak yerine Redis gibi bir önbellekleme katmanı kullanmak, yüksek trafikli e-ticaret sitelerinde sunucu yükünü minimize eder.

Karşılaştırma Modülü İçin Birim Testleri (Unit Testing)

Modülünüzün hatasız çalıştığından emin olmak için Laravel'in sunduğu Pest veya PHPUnit kütüphanelerini kullanarak test senaryoları oluşturmalısınız. Özellikle session manipülasyonlarını test etmek, modülün kararlılığı için hayati önem taşır.

Aşağıdaki test örneği, bir ürünün karşılaştırma listesine başarıyla eklenip eklenmediğini doğrular:

// tests/Feature/ComparisonTest.php
public function test_product_can_be_added_to_comparison()
{
    $product = Product::factory()->create();

    $response = $this->post('/compare/add', [
        'product_id' => $product->id
    ]);

    $response->assertStatus(200);
    $this->assertContains($product->id, session('comparison_list'));
}

Testlerinizi yazarken şu senaryoları mutlaka göz önünde bulundurun:

  • Maksimum ürün limitinin aşılması durumu (örneğin 5 üründen fazlası eklenmemeli).
  • Var olmayan bir ürün ID'si gönderildiğinde sistemin vereceği hata tepkisi.
  • Session süresi dolduğunda karşılaştırma tablosunun boş görünmesi.

Alternatif Yaklaşım: Redis ile Karşılaştırma Listesi Yönetimi

Eğer kullanıcılarınızın karşılaştırma listelerini cihazlar arasında senkronize etmesini istiyorsanız, session yerine Redis kullanmak daha profesyonel bir yaklaşımdır. Redis, anahtar-değer yapısı sayesinde çok hızlı okuma/yazma işlemleri sunar ve verilerin belirli bir süre sonra otomatik silinmesini (TTL) kolaylaştırır.

// Redis kullanımı örneği
use Illuminate\Support\Facades\Redis;

public function addToComparison(Request $request)
{
    $userId = auth()->id();
    $productId = $request->product_id;

    // Kullanıcıya özel bir liste oluştur ve ID'yi ekle
    Redis::sadd("user:{$userId}:comparison", $productId);
    
    // Listenin süresini 24 saat olarak ayarla
    Redis::expire("user:{$userId}:comparison", 86400);

    return response()->json(['status' => 'added']);
}

Bu yöntem, özellikle kullanıcı oturumu kapatsa bile karşılaştırma listesinin korunmasını istediğiniz senaryolarda, veritabanı yükünü artırmadan en yüksek performansı sağlar.

Sonuç

Laravel ile dinamik bir ürün karşılaştırma modülü oluşturmak, hem Laravel'in sunduğu session yönetim kolaylığını hem de Eloquent ORM'in gücünü anlamak için mükemmel bir projedir. Bu modülü geliştirirken kullanıcı deneyimini ön planda tutan, asenkron işlemlerle desteklenmiş bir yapı kurduk. Bir sonraki adım olarak, karşılaştırma listesini veritabanı ile senkronize eden "Kullanıcı Profili" entegrasyonu üzerinde çalışabilirsiniz.

Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Canlıya almadan önce tüm form girişlerini doğrulamalı (validation) ve yetkilendirme (authorization) kontrollerini eksiksiz yapmalısınız. Güvenlik, geliştiricinin sorumluluğundadır.

Bu yazıya tepkinizi paylaşın:
Emre Çelik

Eğitici içerik tasarımı ve yapılandırılmış metin oluşturma konusunda deneyimliyim. Kullanıcıların doğrudan sonuca ulaşmasını sağlayan net ve yalın bir anlatım tarzım var.

Yorumlar (0)

Yorum Yaz