TL;DR: Laravel için fiyatları hiçbir zaman saklamayan bir sepet paketi geliştirdim. Bunun yerine, fiyatları çalışma zamanında çözümlüyor – fiyat manipülasyonu saldırılarını ve eski fiyat hatalarını sonsuza dek ortadan kaldırıyor.
Geleneksel Sepet Paketlerindeki Sorun
Geleneksel Sepet Paketlerindeki Sorun
Kullandığım her Laravel sepet paketi aynı temel hataya sahip: ürün sepetinize eklendiği anda fiyatı saklıyorlar.
Bu gerçek sorunlar yaratıyor:
// Kullanıcı $49.99 olan ürünü ekler
Cart::add($product); // Saklanan fiyat: $49.99
// Yönetici fiyatı $59.99 olarak günceller
$product->update(['price' => 5999]);
// Kullanıcı saatler sonra ödeme yaparken... hala $49.99 ödüyor
// Ya da daha kötüsü: DOM'u inceleyip, saklanan fiyatı bulup, manipüle ediyor
ESKİ FİYAT. Fiyat manipülasyonu zafiyetleri. Flaş satışlar sırasında yarış durumları.
Bunu düzgün bir şekilde düzeltmeye karar verdim.
Cartly’i Tanıtıyorum: Laravel için Gerçek Zamanlı Fiyat Çözümleme
Cartly’i Tanıtıyorum: Laravel için Gerçek Zamanlı Fiyat Çözümleme
Aylardır geliştirme sonrası Cartly‘yi sunuyorum – temelde farklı bir yaklaşıma sahip bir alışveriş sepeti kütüphanesi.
composer require vanthao03596/cartly
Önemli ilke: Fiyatlar asla saklanmaz. Her seferinde, ödeme zamanında çözümlenir.
use Cart\Cart;
// Sepete ekle - fiyat saklanmaz
$item = Cart::add($product, quantity: 2);
// Fiyat erişildiğinde taze olarak çözümlenir
$subtotal = Cart::subtotal(); // Her zaman güncel
$total = Cart::total(); // Her zaman doğru
Gerçek Zamanlı Çözümlemenin Önemi
Gerçek Zamanlı Çözümlemenin Önemi
1. Tasarımda Güvenlik
1. Tasarımda Güvenlik
Fiyat manipülasyonu saldırıları imkansız hale geliyor. Manipüle edilecek saklanan fiyat yok.
// Geleneksel paket - savunmasız
$_SESSION['cart']['item_1']['price'] = 100; // Saldırgan fiyatı değiştirir
// Cartly - manipüle edilecek fiyat yok
// Fiyat çalışma zamanında güvenilir kaynaktan çözümlenir
2. Flaş Satışlar Gerçekten Çalışır
2. Flaş Satışlar Gerçekten Çalışır
// Flaş satış başlar
$product->update(['price' => 1999]); // %50 indirim!
// Tüm sepetler hemen yeni fiyatı yansıtır
// "Üzgünüm, o satış sona erdi" hatası ödeme aşamasında yok
3. Bağlama Duyarlı Fiyatlandırma
3. Bağlama Duyarlı Fiyatlandırma
Fiyatlar kullanıcı, para birimi, yerel ayar veya herhangi bir iş mantığına göre değişebilir:
class TieredPriceResolver implements PriceResolver
{
public function resolve(CartItem $item, CartContext $context): ResolvedPrice
{
$user = $context->user();
return match(true) {
$user?->isPremium() => new ResolvedPrice(cents: 1999),
$user?->isWholesale() => new ResolvedPrice(cents: 1499),
default => new ResolvedPrice(cents: 2499),
};
}
Performans: Toplu Çözümleme N+1’i Ortadan Kaldırır
Performans: Toplu Çözümleme N+1’i Ortadan Kaldırır
“Ama fiyatların çalışma zamanında çözümlenmesi yavaş olmalı!”
Toplu çözümleme ile değil:
// Geleneksel yaklaşım - N+1 sorguları
foreach ($cart->items() as $item) {
$price = $item->product->price; // Her ürün için sorgu
}
// Cartly - Tek toplu sorgu
public function resolveMany(CartItemCollection $items, CartContext $context): array
{
$ids = $items->pluck('id')->all();
$prices = Price::whereIn('product_id', $ids)->get()->keyBy('product_id');
return $items->mapWithKeys(fn($item) => [
$item->rowId => new ResolvedPrice(cents: $prices[$item->id]->amount)
])->all();
}
Cartly otomatik olarak modelleri ve fiyatları topluca yükler. Model için bir sorgu, fiyatlar için bir sorgu – sepet boyutundan bağımsız olarak.
Gerçekten Önemli Özellikler
Gerçekten Önemli Özellikler
Birden Fazla Sepet Örneği
Birden Fazla Sepet Örneği
Sepet, istekte bulunan liste ve karşılaştırma listeleri tam ayrışma ile:
// Ana sepet
Cart::add($product);
// İstek listesi
Cart::wishlist()->add($product);
// Karşılaştır // (en fazla 4 öğe)
Cart::compare()->add($product);
// Örnekler arasında taşı
Cart::moveToWishlist($rowId);
Cart::moveToCart($rowId);
Esnek Koşullar Sistemi
Esnek Koşullar Sistemi
Vergi, indirim, nakliye – açık bir sıralama kontrolü ile:
use Cart\Conditions\TaxCondition;
use Cart\Conditions\DiscountCondition;
// Öncelikle %20 indirim uygulandı
Cart::condition(new DiscountCondition(
name: 'Yaz İndirimi',
value: 20,
mode: 'yüzde',
order: 1
));
// İndirimli tutar üzerinden vergi hesaplanır
Cart::condition(new TaxCondition(
name: 'KDV',
rate: 10,
order: 2
));
// Şeffaf bir ayrıntı almak için
$breakdown = Cart::getCalculationBreakdown();
// [
// 'subtotal' => 10000,
// 'conditions' => [
// 'Yaz İndirimi' => -2000,
// 'KDV' => 800,
// ],
// 'total' => 8800
// ]
Birden Fazla Depolama Sürücüsü
Birden Fazla Depolama Sürücüsü
Mimarinize uygun olanı seçin:
| Sürücü | En İyi Kullanım Alanı |
|---|---|
| Oturum | Durumsuz uygulamalar, hızlı kurulum |
| Veritabanı | Kalıcı sepetler, kullanıcı hesapları |
| Önbellek | Yüksek performans, Redis/Memcached |
| Dizi | Test |
// config/cart.php
'driver' => 'database',
// Veya örnek başına
'instances' => [
'default' => ['driver' => 'database'],
'compare' => ['driver' => 'session'],
]
Misafirden Kullanıcıya Sepet Birleştirme
Misafirden Kullanıcıya Sepet Birleştirme
Kullanıcılar giriş yaptığında otomatik sepet birleştirme:
'associate' => [
'auto_associate' => true,
'merge_on_login' => true,
'merge_strategy' => 'combine', // combine | keep_guest | keep_user
]
Geliştirici Deneyimi
Geliştirici Deneyimi
Tüm Fiyatlar Sentlerde
Tüm Fiyatlar Sentlerde
Artık ondalık hassasiyet hatası yok:
// İçeride: her şey sent olarak
$subtotal = Cart::subtotal(); // 4999 (49.99 değil)
// Gösterim: insanlar için formatlanmış
$formatted = Cart::subtotal(formatted: true); // "$49.99"
// Yardımcılar dahil
format_price(4999); // "$49.99"
cents_to_dollars(4999); // 49.99
dollars_to_cents(49.99); // 4999
Birinci Sınıf Test Desteği
Birinci Sınıf Test Desteği
use Cart\Cart;
public function test_checkout_calculates_correct_total()
{
Cart::fake();
Cart::factory()
->withItems([
['id' => 1,
'quantity' => 2,
'price' => 1000],
['id' => 2,
'quantity' => 1,
'price' => 2500],
])
->withCondition(new TaxCondition('KDV', 10))
->create();
Cart::assertSubtotal(4500);
Cart::assertTaxTotal(450);
Cart::assertTotal(4950);
}
Olay Tabanlı Mimari
Olay Tabanlı Mimari
Her sepet işlemi için kancalar:
// Tam yaşam döngüsü kapsama için 12 olay
CartItemAdding / CartItemAdded
CartItemUpdating / CartItemUpdated
CartItemRemoving / CartItemRemoved
CartClearing / CartCleared
CartMerging / CartMerged
CartConditionAdded / CartConditionRemoved
Hızlı Başlangıç
Hızlı Başlangıç
composer require vanthao03596/cartly
php artisan vendor:publish --provider="Cart\CartServiceProvider" --tag="config"
Modelinizi satın alınabilir yapmak için:
use Cart\Contracts\Buyable;
use Cart\Contracts\Priceable;
use Cart\Traits\CanBeBought;
class Product extends Model implements Buyable, Priceable
{
use CanBeBought;
// İşte bu kadar - fiyat, yaygın niteliklerden otomatik olarak tespit edilir
// (price, sale_price, current_price, vb.)
}
Kullanıma başlayın:
use Cart\Cart;
// Öğeleri ekle
Cart::add($product, quantity: 2, options: ['size' => 'L']);
// Toplamları al
$total = Cart::total(formatted: true); // "$99.98"
// Sepeti temizle
Cart::clear();
Bunu Neden Yaptım
Bunu Neden Yaptım
Yıllardır e-ticaret sistemleri kuruyorum. Her zaman ya:
- Mevcut bir paketi kullancıydım ve sınırlamalarıyla savaşıyordum
- Özel bir sepet inşa etmem gerekiyordu
Hiçbiri tatmin edici değildi. Mevcut paketler fiyatları saklıyordu (güvenlik/güncel olmama sorunları). Özel çözümler ise her projede tekerleği yeniden icat etmeyi gerektiriyordu.
Cartly, beş yıl önce sahip olmayı istediğim sepet kütüphanesidir:
- Varsayılan olarak güvenli – fiyat saklaması olmadığı için manipülasyon yok
- Her zaman güncel – gerçek zamanlı çözümleme, eski anlık görüntüler değil
- Genişletilebilir – herhangi bir bileşeni fork yapmadan değiştirebilirsiniz
- İyi test edilmiş – kapsamlı test setiyle test araçları
- Doğru bir şekilde yazılmış – tam PHP 8.1+ tür güvenliği
Bağlantılar
Bağlantılar
Sırada Ne Var?
Sırada Ne Var?
Bu paketi aktif bir şekilde bakım altında tutuyorum ve:
- Daha fazla yerleşik koşul türü
- Livewire/Inertia bileşen örnekleri
Eğer bu yaklaşım sizinle rezonansa giriyorsa, repo’yu yıldızlayın. Geri bildirim ve katkılar bekleniyor!
Kaynak: Orijinal Makale
- Geleneksel Sepet Paketlerindeki Sorun
- Cartly’i Tanıtıyorum: Laravel için Gerçek Zamanlı Fiyat Çözümleme
- Gerçek Zamanlı Çözümlemenin Önemi
- Performans: Toplu Çözümleme N+1’i Ortadan Kaldırır
- Gerçekten Önemli Özellikler
- Birden Fazla Sepet Örneği
- Esnek Koşullar Sistemi
- Birden Fazla Depolama Sürücüsü
- Misafirden Kullanıcıya Sepet Birleştirme
- Geliştirici Deneyimi
- Hızlı Başlangıç
- Bunu Neden Yaptım
- Bağlantılar
- Sırada Ne Var?


