Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce geliştirme ortamınızın güncel olduğundan emin olmalısınız. Laravel 11 veya üzeri bir sürüm kullanmanız, modern PHP 8.3+ özelliklerinden faydalanmanızı sağlar. İhtiyacınız olan temel araçlar şunlardır:
- PHP 8.3 veya daha yüksek bir sürüm.
- Composer paket yöneticisi.
- MySQL veya PostgreSQL veritabanı sistemi.
- Redis (Opsiyonel: Sepet verilerinin hızlı erişimi için önerilir).
Kurulumu doğrulamak için terminalinizde php -v komutunu çalıştırarak sürümünüzü kontrol edebilirsiniz. Projenizi oluşturduktan sonra veritabanı bağlantı ayarlarınızı .env dosyasında yapılandırdığınızdan emin olun.
Adım 1: Sepet Veri Modeli ve Veritabanı Tasarımı
Sepet verilerini yönetmek için iki ana yaklaşım vardır: Sadece oturum tabanlı (Session) veya veritabanı destekli (Database). Profesyonel projelerde kalıcılık sağlamak için veritabanı destekli yapıyı tercih ederiz. İlk olarak, sepet öğelerini tutacak migration dosyamızı oluşturalım.
// Terminal üzerinden migration oluşturma
php artisan make:migration create_cart_items_table
Oluşturulan migration dosyasını aşağıdaki yapıya göre düzenleyin. Bu yapı, ürün kimliği, miktar ve kullanıcı ilişkisini güvenli bir şekilde saklamamıza olanak tanır.
public function up(): void
{
Schema::create('cart_items', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->nullable()->constrained()->onDelete('cascade');
$table->foreignId('product_id')->constrained()->onDelete('cascade');
$table->integer('quantity')->default(1);
$table->string('session_id')->nullable(); // Misafir kullanıcılar için
$table->timestamps();
});
}
Adım 2: Sepet Servis Sınıfı ile Mantıksal Yönetim
Sepet işlemlerini Controller içerisinde yazmak yerine, temiz kod (Clean Code) prensipleri gereği bir CartService sınıfı oluşturmalıyız. Bu sınıf, sepete ekleme, çıkarma ve güncelleme gibi işlemleri merkezi bir noktadan yönetmemizi sağlar.
namespace App\Services;
use App\Models\CartItem;
class CartService
{
public function addToCart($productId, $quantity = 1)
{
return CartItem::updateOrCreate(
['user_id' => auth()->id(), 'product_id' => $productId],
['quantity' => \DB::raw("quantity + $quantity")]
);
}
}
Bu servis, updateOrCreate metodunu kullanarak aynı ürün tekrar eklendiğinde yeni bir satır oluşturmak yerine miktarı artırır. Bu, veritabanı performansını optimize eden kritik bir yaklaşımdır.
Adım 3: Sepet İşlemleri İçin Controller Yapısı
Kullanıcıdan gelen istekleri karşılamak için CartController oluşturacağız. Burada form doğrulama (Validation) kuralları, uygulamanın güvenliği için vazgeçilmezdir. Özellikle quantity değerinin pozitif bir tamsayı olduğundan emin olmalıyız.
public function store(Request $request, CartService $cartService)
{
$validated = $request->validate([
'product_id' => 'required|exists:products,id',
'quantity' => 'required|integer|min:1'
]);
$cartService->addToCart($validated['product_id'], $validated['quantity']);
return response()->json(['message' => 'Ürün sepete eklendi.'], 200);
}
Adım 4: Sepet Verilerinin Dinamik Olarak Listelenmesi
Sepet sayfasında ürünleri listelerken, veritabanı sorgularını optimize etmek için with('product') metodunu kullanarak "N+1" sorununu önlemeliyiz. Bu, Laravel'in Eloquent ORM yapısında sıkça karşılaşılan bir performans darboğazıdır.
public function index()
{
$cartItems = CartItem::where('user_id', auth()->id())
->with('product')
->get();
return view('cart.index', compact('cartItems'));
}
Sepet Yönetim Yöntemlerinin Karşılaştırılması
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Session Tabanlı | Çok hızlı, veritabanı yükü yok. | Kullanıcı çıkış yapınca sepet silinir. |
| Veritabanı Tabanlı | Kalıcı sepet, cihazlar arası senkronizasyon. | Daha fazla sorgu yükü. |
| Redis (Cache) | Çok hızlı ve kalıcı (yapılandırılabilir). | Ekstra altyapı maliyeti. |
Kritik Güvenlik Uyarısı: Sepet işlemlerinde fiyat verilerini asla istemciden (frontend) almayın. Fiyatı her zaman veritabanındaki ürün tablosundan çekin. Aksi takdirde, kötü niyetli kullanıcılar tarayıcı konsolu üzerinden ürün fiyatını değiştirerek ödeme yapmaya çalışabilirler.
Adım 5: Sepet Güncelleme ve Silme İşlemleri
Kullanıcıların sepetindeki miktarları değiştirmesi veya ürünü tamamen kaldırması için rotalarımızı tanımlamalı ve Controller içerisinde ilgili metodları yazmalıyız. DELETE metodunu kullanırken CSRF korumasını ihmal etmeyin.
public function destroy($id)
{
$item = CartItem::where('user_id', auth()->id())->findOrFail($id);
$item->delete();
return back()->with('success', 'Ürün sepetten kaldırıldı.');
}
Sıkça Sorulan Sorular
Sepet verilerini veritabanında tutmak performansı düşürür mü?
Doğru indeksleme (index) yapıldığı sürece veritabanı performansı düşmez. user_id ve product_id alanlarına indeks ekleyerek sorgu hızını optimize edebilirsiniz.
Misafir kullanıcılar için sepeti nasıl yönetmeliyim?
Misafir kullanıcılar için session_id kullanarak geçici bir sepet oluşturabilir, kullanıcı giriş yaptığında bu verileri veritabanına taşıyabilirsiniz.
Sepet verisi ne zaman temizlenmelidir?
Satın alma işlemi başarıyla tamamlandığında veya sepet öğeleri belirli bir süre (örneğin 30 gün) güncellenmediğinde temizlenmelidir.
Redis kullanmak zorunda mıyım?
Küçük ölçekli projeler için zorunlu değildir, ancak yüksek trafikli e-ticaret sitelerinde Redis, veritabanı üzerindeki yükü ciddi oranda azaltır.
Fiyat güncellemeleri sepeti nasıl etkiler?
Sepet öğeleri her yüklendiğinde veritabanındaki güncel fiyatı çekmek en güvenli yoldur. Eğer kullanıcı sepete eklediği andaki fiyatı sabitlemek istiyorsanız, fiyatı cart_items tablosuna da kaydedebilirsiniz.
Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Üretim ortamında (production) kullanmadan önce tüm girdileri doğrulamalı (validation) ve yetkilendirme (authorization) kontrollerini eksiksiz uygulamalısınız.
Sepet Sistemlerinde Performansı Artırmak İçin İleri İpuçları
Sepet yönetimi, yüksek trafikli e-ticaret sitelerinde veritabanı üzerindeki yükü artıran en kritik süreçlerden biridir. Kullanıcı her sayfayı yenilediğinde veya sepete bir ürün eklediğinde veritabanına sorgu göndermek, özellikle büyük ölçekli projelerde darboğaz yaratabilir. Bu noktada performansı optimize etmek için şu stratejileri uygulayabilirsiniz:
- Redis ile Önbellekleme: Sepet verilerini veritabanı yerine Redis üzerinde tutmak, okuma ve yazma hızını milisaniyelere indirir. Laravel'in
Cachefacade yapısını kullanarak sepet verisini kolayca Redis'e taşıyabilirsiniz. - Eager Loading Kullanımı: Sepet içeriğini listelerken
with('product')metodunu kullanarak N+1 sorgu problemini engelleyin. Bu, her bir sepet öğesi için ayrı bir ürün sorgusu atılmasını önleyerek tek bir sorgu ile tüm veriyi çekmenizi sağlar. - Asenkron İşlemler: Sepet güncellemeleri sırasında stok kontrolü gibi ağır işlemleri Laravel Queues (Kuyruklar) ile arka plana atarak kullanıcının bekleme süresini azaltın.
// Sepet verisini Redis üzerinde önbelleğe alma örneği
public function getCartFromCache($userId)
{
return Cache::remember("user_cart_{$userId}", 3600, function () use ($userId) {
return Cart::where('user_id', $userId)->with('product')->get();
});
}
Sepet Süreçleri İçin Otomatik Test Yazımı
Sepet sistemi, finansal verilerle doğrudan ilişkili olduğu için hata payı kabul etmeyen bir alandır. Bir ürünün sepete eklenmesi, miktarının güncellenmesi ve toplam tutarın hesaplanması süreçlerini Pest veya PHPUnit kullanarak test etmelisiniz. Bu, gelecekte yapacağınız güncellemelerin mevcut işleyişi bozmadığından emin olmanızı sağlar.
Aşağıdaki örnek, bir ürünün sepete başarıyla eklenip eklenmediğini kontrol eden temel bir Feature Test yapısını göstermektedir:
public function test_user_can_add_product_to_cart()
{
$user = User::factory()->create();
$product = Product::factory()->create(['price' => 100]);
$response = $this->actingAs($user)->post('/cart/add', [
'product_id' => $product->id,
'quantity' => 1
]);
$response->assertStatus(200);
$this->assertDatabaseHas('cart_items', [
'user_id' => $user->id,
'product_id' => $product->id,
'quantity' => 1
]);
}
Bu test senaryolarını genişleterek; stokta olmayan ürünlerin sepete eklenmesini engelleme, negatif miktar girilmesi durumunda hata döndürme ve indirim kuponlarının toplam tutara etkisini doğrulama gibi kritik durumları da kapsama alanına almalısınız. Güvenli ve sürdürülebilir bir e-ticaret altyapısı için test odaklı geliştirme (TDD) yaklaşımını benimsemek, uzun vadede hata ayıklama maliyetlerinizi ciddi oranda düşürecektir.
Sonuç
Laravel ile dinamik bir sepet yönetim sistemi kurmak, veritabanı ilişkileri ve servis odaklı mimariyi anlamakla başlar. Bu rehberde, ürünleri sepete ekleme, güncelleme ve silme süreçlerini profesyonel standartlarda nasıl yöneteceğinizi adım adım inceledik. Bir sonraki adım olarak, sepet verilerini bir ödeme geçidi (Payment Gateway) ile entegre ederek sipariş oluşturma sürecini tamamlayabilirsiniz.


Yorumlar (0)
Yorum Yaz