shopper/cart
Laravel package for managing a shopping cart: add/update/remove items, handle quantities, totals, and cart persistence across requests or sessions. Designed to integrate into e‑commerce apps with a simple API and configurable storage.
Installation
composer require shopper/cart
Verify shopper/core is auto-installed as a dependency.
Service Provider Binding
Register the package in config/app.php under providers:
Shopper\Cart\CartServiceProvider::class,
First Cart Operation
use Shopper\Cart\Facades\Cart;
// Add an item
Cart::addItem('product_123', [
'name' => 'Laravel T-Shirt',
'price' => 29.99,
'quantity' => 1,
]);
// Get cart summary
$cart = Cart::get();
dd($cart['total']);
Pipeline Configuration
Publish the config and customize pipeline steps in config/cart.php:
'pipeline' => [
'steps' => [
'subtotal',
'tax',
'discount',
'shipping',
'total',
],
],
Use Laravel’s service container to extend the pipeline dynamically:
// In a service provider (e.g., AppServiceProvider)
public function register()
{
Cart::extend(function ($cart) {
$cart->addPipelineStep('loyalty_discount', function ($cart) {
if (auth()->user()->isGoldMember()) {
return $cart->subtotal * 0.15; // 15% loyalty discount
}
return 0;
});
});
}
Events Listen to cart updates via Laravel’s event system:
// Register in EventServiceProvider
Cart::onUpdate(function ($cart) {
event(new CartUpdated($cart));
});
Queues Offload heavy calculations to queues:
Cart::calculate(function ($cart) {
// This runs in a queue job
return $cart->applyComplexDiscounts();
});
API Resources Format cart responses with Laravel’s API Resources:
namespace App\Http\Resources;
use Shopper\Cart\Facades\Cart;
use Illuminate\Http\Resources\Json\JsonResource;
class CartResource extends JsonResource
{
public function toArray($request)
{
return [
'items' => Cart::get()['items'],
'total' => Cart::get()['total'],
'currency' => config('cart.currency'),
];
}
}
Use Laravel’s context binding to manage tenant-specific carts:
// In a middleware or service provider
Cart::setContext('tenant_id_' . auth()->id());
Pipeline Order Matters
config/cart.php. Reordering can break calculations.State Mutability
$cartClone = clone Cart::get();
Missing Documentation
addItem validation rules).php artisan tinker to explore the API:
Cart::addItem('test', ['price' => 10]);
Cart::get();
PHP 8.3 Requirements
Log Pipeline Steps Add debug logging to track pipeline execution:
Cart::extend(function ($cart) {
$cart->addPipelineStep('debug', function ($cart) {
\Log::debug('Pipeline state:', $cart->toArray());
return 0;
});
});
Isolate Pipeline Steps Temporarily disable steps to identify misbehaving logic:
// In config/cart.php
'pipeline' => [
'steps' => ['subtotal', 'tax'], // Disable others for testing
],
Handle Exceptions Gracefully Wrap pipeline execution in a try-catch:
try {
$cart = Cart::calculate();
} catch (\Shopper\Cart\Exceptions\PipelineException $e) {
\Log::error('Cart calculation failed:', ['error' => $e->getMessage()]);
return response()->json(['error' => 'Cart processing error'], 500);
}
Custom Pipeline Steps Create reusable pipeline logic in a trait or service:
// app/Services/CartExtensions.php
namespace App\Services;
use Shopper\Cart\Facades\Cart;
class CartExtensions
{
public static function addBulkDiscount()
{
Cart::extend(function ($cart) {
$cart->addPipelineStep('bulk_discount', function ($cart) {
$total = $cart->subtotal;
if ($total > 1000) {
return $total * 0.2; // 20% discount
}
return 0;
});
});
}
}
Override Core Logic Replace default pipeline steps (e.g., tax calculation):
Cart::extend(function ($cart) {
$cart->removePipelineStep('tax');
$cart->addPipelineStep('tax', function ($cart) {
// Custom tax logic
return $cart->subtotal * 0.08; // 8% flat tax
});
});
Laravel Caching Integration Cache cart calculations to reduce pipeline overhead:
use Illuminate\Support\Facades\Cache;
$cartKey = 'cart_' . auth()->id();
$cart = Cache::remember($cartKey, now()->addHours(1), function () {
return Cart::calculate();
});
Avoid N+1 Queries If using Eloquent models, eager-load relationships:
$items = Product::whereIn('id', $cartItemIds)->with('category')->get();
Pipeline Caching Cache the entire pipeline result if calculations are expensive:
Cache::remember('cart_total_' . auth()->id(), now()->addMinutes(5), function () {
return Cart::get()['total'];
});
Queue-Based Calculations Offload heavy calculations to queues:
Cart::calculate(function ($cart) {
// This runs in a queue job
return $cart->applyComplexPromotions();
})->onQueue('high');
Use Laravel Events Trigger events for cart updates:
// In CartServiceProvider
Cart::onUpdate(function ($cart) {
event(new \App\Events\CartUpdated($cart));
});
Leverage Laravel Policies Secure cart operations with policies:
// app/Policies/CartPolicy.php
public function update(User $user, Cart $cart)
{
return $user->id === $cart->user_id;
}
API Testing Test cart endpoints with Laravel’s HTTP tests:
public function test_add_to_cart()
{
$response = $this->postJson('/cart', [
'product_id' => '123',
'quantity' => 2,
]);
$response->assertStatus(200)
->assertJson(['total' => 59.98]);
}
How can I help you explore Laravel packages today?