From 4f87bd645cced226cf8473ac418512baeeed00d5 Mon Sep 17 00:00:00 2001 From: Joel Male Date: Wed, 27 May 2026 21:53:37 +1000 Subject: [PATCH] docs: update README for v3 features - Fix vendor:publish tag to cart-config - Update TOC with Storage Drivers, Artisan Generators, First-class Objects, Testing, and Livewire / Inertia sections - Replace Storage Options section with expanded Storage Drivers section covering session, database, Redis, multi-driver, and custom drivers - Add Artisan Generators section documenting cart:install, cart:make:coupon, cart:make:tax, cart:make:shipping, cart:make:driver, and cart:debug - Add First-class Objects section documenting Coupon, TaxRule, and ShippingRate base classes - Add Testing section documenting Cart::fake() and assertion methods - Add Livewire / Inertia section documenting HasCart trait and ShareCartWithInertia --- README.md | 275 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 253 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 41a9245..a5bb622 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,11 @@ ## Table of Contents - [Basic Usage](#basic-usage) - [Conditions](#conditions) - [Cart Items](#cart-items) - - [Database Support](#database-support) + - [Storage Drivers](#storage-drivers) + - [Artisan Generators](#artisan-generators) + - [First-class Objects](#first-class-objects) + - [Testing](#testing) + - [Livewire / Inertia](#livewire--inertia) - [Events](#events) - [Credits](#-credits) - [License](#-license) @@ -73,7 +77,7 @@ ### ⚙️ Configuration You can publish the configuration file to customize various options. ```php -php artisan vendor:publish --provider="Wearepixel\Cart\CartServiceProvider" --tag="config" +php artisan vendor:publish --provider="Wearepixel\Cart\CartServiceProvider" --tag="cart-config" ``` #### Formatting Numbers @@ -693,55 +697,282 @@ ### Cart Items $item->getPriceSumWithConditions(); ``` -### Storage Options +### Storage Drivers -By default the cart is stored in the session, but there are times you may want to store the cart in the database. +The cart supports multiple storage backends via a driver system. -For instance, you may want to store the cart in the database so that the cart can be retrieved even after the user logs out or closes the browser, or you may want to add cart timeouts and support for multiple computers. +#### Session (default) -#### Session +Cart data is stored in the Laravel session. No configuration needed. -The cart is stored in the session by default, using Laravel's in-built SessionManager. +#### Database -#### Database Support +Store the cart in a database table for persistence across sessions. -To get started, you'll need to create a new model for your Cart, the package requires only 3 columns, but you're free to extend this as you wish and add more columns. - -You can utilise the [events](#events) provided by the package to store additional information alongside the cart. +**1. Create a migration:** ```php -$table->string('session_id'); // this handles the session id of the cart -$table->text('items'); // this will store the cart items -$table->text('conditions'); // this will store the cart level conditions +$table->string('session_id'); +$table->text('items'); +$table->text('conditions'); ``` -Then add some json casts to your model and fillable columns: +**2. Add casts to your model:** ```php protected $guarded = []; protected $casts = [ - 'items' => 'array', + 'items' => 'array', 'conditions' => 'array', ]; ``` -Then update the configuration file to use the database driver: +**3. Update `config/cart.php`:** ```php 'driver' => 'database', -'storage' => [ - 'session', +'drivers' => [ 'database' => [ - 'model' => \App\Models\Cart::class, // your model here - 'id' => 'session_id', - 'items' => 'items', + 'model' => \App\Models\Cart::class, + 'id' => 'session_id', + 'items' => 'items', 'conditions' => 'conditions', ], ], ``` +#### Redis + +Store the cart in Redis with an optional TTL. + +```php +'driver' => 'redis', + +'drivers' => [ + 'redis' => [ + 'connection' => 'default', + 'ttl' => 604800, // 7 days in seconds + ], +], +``` + +#### Multi-driver + +Write to multiple drivers simultaneously. Reads come from the first driver listed. + +```php +'driver' => 'multi', + +'drivers' => [ + 'multi' => ['session', 'database'], +], +``` + +#### Custom driver + +Generate a custom driver stub with `php artisan cart:make:driver MyDriver` then register it in `CartManager`. + +### Artisan Generators + +#### Install: **cart:install** + +Publishes the config file and scaffolds `app/Cart/` with subdirectories for your coupons, tax rules, shipping rates, and custom drivers. + +```bash +php artisan cart:install +``` + +#### Generate a Coupon: **cart:make:coupon** + +```bash +php artisan cart:make:coupon TenPercentOff +``` + +Creates `app/Cart/Coupons/TenPercentOff.php` extending `Wearepixel\Cart\Coupons\Coupon`. + +#### Generate a Tax Rule: **cart:make:tax** + +```bash +php artisan cart:make:tax GstTaxRule +``` + +Creates `app/Cart/Tax/GstTaxRule.php` extending `Wearepixel\Cart\Tax\TaxRule`. + +#### Generate a Shipping Rate: **cart:make:shipping** + +```bash +php artisan cart:make:shipping FlatRateShipping +``` + +Creates `app/Cart/Shipping/FlatRateShipping.php` extending `Wearepixel\Cart\Shipping\ShippingRate`. + +#### Generate a Custom Driver: **cart:make:driver** + +```bash +php artisan cart:make:driver ElasticsearchDriver +``` + +Creates `app/Cart/Drivers/ElasticsearchDriver.php` implementing `CartDriver`. + +#### Debug: **cart:debug** + +Dumps the current cart state. Not available in production. + +```bash +php artisan cart:debug +``` + +### First-class Objects + +Instead of building raw `CartCondition` arrays, you can extend the provided base classes. + +#### Coupon + +```php +namespace App\Cart\Coupons; + +use Wearepixel\Cart\Coupons\Coupon; + +class TenPercentOff extends Coupon +{ + protected string $code = 'SAVE10'; + protected string $value = '-10%'; + protected string $target = 'subtotal'; + + public function isValid(): bool + { + return true; // add your own validation logic + } +} + +// Apply to the cart +Cart::coupon(new TenPercentOff); +``` + +#### TaxRule + +```php +namespace App\Cart\Tax; + +use Wearepixel\Cart\Tax\TaxRule; + +class GstTaxRule extends TaxRule +{ + protected string $name = 'GST'; + protected string $value = '10%'; + protected string $target = 'subtotal'; + + public function isApplicable(): bool + { + return true; + } +} + +Cart::tax(new GstTaxRule); +``` + +#### ShippingRate + +```php +namespace App\Cart\Shipping; + +use Wearepixel\Cart\Shipping\ShippingRate; + +class FlatRateShipping extends ShippingRate +{ + protected string $name = 'Standard Shipping'; + protected string $value = '+10'; + protected string $target = 'total'; + + public function isApplicable(): bool + { + return true; + } +} + +Cart::shipping(new FlatRateShipping); +``` + +### Testing + +#### Cart::fake() + +`Cart::fake()` replaces the active driver with an in-memory `NullDriver` and returns a `CartFactory` for seeding test state. + +```php +use Wearepixel\Cart\Cart; + +// In your test +$factory = app('cart')->fake(); + +$factory->withItems(3); +$factory->withCondition(new CartCondition(['name' => 'GST', 'type' => 'tax', 'value' => '10%', 'target' => 'subtotal'])); + +// Or chain it +app('cart')->fake()->withItems(2)->withCondition($condition); +``` + +#### Assertion Methods + +After `fake()`, the `Cart` instance exposes assertion methods: + +```php +$cart = app('cart'); +$cart->fake(); +$cart->add(1, 'Widget', 50.00, 2); + +$cart->assertContains(1); // item exists +$cart->assertCount(1); // 1 distinct item +$cart->assertTotalQuantity(2); // 2 units +$cart->assertSubTotal(100.00); // subtotal +$cart->assertTotal(100.00); // total +$cart->assertNotEmpty(); // cart has items +$cart->assertEmpty(); // cart is empty +$cart->assertConditionApplied('GST'); // condition present +``` + +### Livewire / Inertia + +#### HasCart trait (Livewire) + +Add `HasCart` to any Livewire component to get reactive cart state and proxy methods. + +```php +use Wearepixel\Cart\Concerns\HasCart; + +class CartComponent extends Component +{ + use HasCart; + + // $cartItems, $cartCount, $cartSubTotal, $cartTotal are auto-populated + + public function addToCart(int $id, string $name, float $price): void + { + $this->cartAdd($id, $name, $price, 1); + // $cartCount, $cartSubTotal etc. update automatically + } +} +``` + +#### ShareCartWithInertia (Inertia) + +Share cart state on every Inertia response from your `HandleInertiaRequests` middleware: + +```php +use Wearepixel\Cart\Concerns\ShareCartWithInertia; + +public function share(Request $request): array +{ + return array_merge(parent::share($request), [ + 'cart' => fn() => ShareCartWithInertia::data(), + ]); +} +``` + +This shares `cart.items`, `cart.subtotal`, `cart.total`, and `cart.count` with every page. + ### Events The package provides a few events that you can listen to in order to manipulate the cart or take actions based on cart events.