wearepixel/laravel-cart
A Laravel shopping cart package for managing cart items, quantities, prices, and totals with flexible storage options. It provides a simple API for adding, updating, and removing items, making it easy to integrate into ecommerce checkout flows.
Coupon, TaxRule, and ShippingRate abstract classes mean coupons, tax, and shipping logic no longer has to be hand-rolled as ad-hoc CartCondition arrays. That removes a chunk of the "we'd have to build it ourselves anyway" argument for greenfield carts.SessionDriver, DatabaseDriver, RedisDriver, NullDriver, MultiDriver) lets you ship a session-backed cart for MVP and migrate to persistent, multi-device carts later without re-architecting the cart domain. That is a genuine roadmap de-risker and worth planning the migration path around now.DatabaseDriver / RedisDriver / MultiDriver make these a config decision rather than a rewrite — treat them as newly feasible roadmap items.HasCart (Livewire reactive properties) and ShareCartWithInertia (Inertia shared props) mean cart UI is no longer a reason to pick one frontend stack. This unblocks the "Livewire vs. Inertia/Vue" decision to be made on other grounds.Cart::fake(), CartFactory with withItems() / withCondition() / withCoupon(), and the assertion set (assertTotal(), assertConditionApplied(), etc.) mean cart behavior is testable without hitting session or DB. Budget for checkout/cart tests drops, and this is the single strongest signal of production-readiness in the release.cart:install plus cart:make:coupon|tax|shipping|driver generators impose a conventional app/Cart/ structure. That's a real architectural opinion — decide whether to adopt it or fight it.applies_to (limit a condition to the first N units of a line item) directly enables "buy 2 get 1 free", tiered BOGO, and per-unit discount campaigns that previously required custom condition code.CartSession is removed, the Cart constructor signature changed (driver instead of raw storage), and the config publish tag was renamed config → cart-config. Container-resolved usage is unaffected, but any code that instantiated Cart directly, type-hinted CartSession, or scripts vendor:publish --tag=config will break. Scope this before committing to the upgrade.Consider adopting when:
Look elsewhere when:
@joelwmale is the sole contributor on v3.0.0). That's the largest strategic risk in this assessment and should be priced accordingly: assume you may own the code.For executives: This release turns a utility cart library into a credible foundation for our commerce surface. Previously we'd have hand-built coupons, tax, and shipping as loose condition objects; v3.0.0 gives us typed, extendable Coupon/TaxRule/ShippingRate classes and a storage layer that lets us start session-based and graduate to persistent, cross-device carts without a rewrite. Two things to weigh: it is still a single-maintainer open-source package (so we should assume some ownership risk, and keep the abstraction thin enough to swap), and it deliberately does not handle payments, tax calculation, or carrier rates — those remain buy decisions. My recommendation is to adopt for cart state and totals, integrate Stripe/TaxJar/carrier APIs behind its condition interfaces, and treat the storage driver system as the insurance policy that keeps our exit cost low.
For engineering: v3.0.0 is a major release with real breaking changes, but they're narrow. CartSession is gone, replaced by the CartDriver interface and CartManager; the Cart constructor now takes a driver rather than raw session/database storage; and the config publish tag moved from config to cart-config. Service-container usage is explicitly unaffected, so audit for direct Cart instantiation, CartSession type-hints, and publish scripts before scheduling the bump. In exchange you get a genuinely better test surface — Cart::fake() swaps in an in-memory NullDriver and hands back a CartFactory for fluent state seeding, with assertions covering contents, counts, quantities, subtotals, totals, and applied conditions — plus Artisan generators (cart:install, cart:make:coupon|tax|shipping|driver) that standardize an app/Cart/ layout. Conditions are now serialized to arrays before storage, which fixes cross-driver serialization drift and is worth double-checking against any custom condition classes that relied on object identity. Also note the Redis driver TTL bug fix (minutes → seconds): if we're on Redis, existing keys were written with wrong expiries and should be validated. PHPStan level 5, zero errors, and Laravel 13 support are in place. The one thing I'd push back on: the single-maintainer bus factor means we should keep our Coupon/TaxRule/ShippingRate subclasses and condition logic in our own namespace, not vendored into the package's structure, so a fork or replacement stays a weekend, not a quarter.
How can I help you explore Laravel packages today?