Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Cart Laravel Package

offline-agency/laravel-cart

A Laravel shopping cart package for adding products, updating quantities, calculating totals, and managing cart data through a simple, framework-friendly API. Designed to integrate cleanly into Laravel applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and publish its assets:

composer require offline-agency/laravel-cart
php artisan vendor:publish --provider="OfflineAgency\LaravelCart\LaravelCartServiceProvider"
php artisan migrate

Work through the published config/cart.php first — it controls the storage driver, the buyable model/table, and (as of 4.1.0) the guest-transfer toggle. Then skim the package's Cart facade / manager class to see the mutation surface (add, update, remove, clear, content, total).

A minimal first use case is adding a purchasable model from a controller:

use OfflineAgency\LaravelCart\Facades\Cart;

public function add(Product $product)
{
    Cart::add($product, quantity: 1);
    return back();
}

Your Product needs to satisfy the package's buyable contract (identifier, name, price). If the package ships a Buyable interface or trait, use it; otherwise the config maps the model and columns explicitly.

Implementation Patterns

Line-item mutations. Treat every cart change as a mutation on an identified line item (id/rowId), not on the underlying model. Add returns or exposes the line identifier, which you use for subsequent update/remove calls. Store that identifier in your UI (hidden input, Livewire property) so quantity changes are unambiguous when the same product is added with different options.

Atomic mutations (4.1.0). Mutations now run inside a transaction for the database driver. This fixes the common partial-write bug where a line item was inserted but the cart totals row was not updated. You still get to compose multi-step operations:

Cart::transaction(function () use ($product, $coupon) {
    Cart::add($product, 2);
    Cart::applyCoupon($coupon);
});

Or rely on the built-in per-mutation atomicity. Batch related writes inside one transaction (add + coupon + shipping) so a failure rolls back the whole change rather than leaving a half-updated cart.

Guest transfer (opt-in). 4.1.0 makes guest-cart-to-user-cart transfer opt-in. Enable it in config/cart.php and wire it to your login flow:

// config/cart.php
'guest_transfer' => true,
Event::listen(Login::class, fn ($event) => Cart::transferGuestCart($event->user));

Decide your merge strategy explicitly: replace the user's existing cart, append guest items, or take the max quantity per line. Most stores want "merge, then delete guest cart," but a subscription or B2B flow may want "guest cart wins."

Checkout handoff. Snapshot the cart into an order at checkout rather than reading it live — prices and options can change between cart view and payment. Persist line items with their price-at-time-of-add so a price update mid-session doesn't silently change the order total.

Testing. Use the package's array/in-memory driver (or the session driver in a test) so cart tests don't touch the DB. Assert on content() and total() rather than raw session payloads, so your tests survive a storage-driver swap.

Gotchas and Tips

  • Guest transfer is now opt-in. If you upgrade from 4.0.x and relied on automatic transfer, users will silently lose their guest carts on login. Set guest_transfer => true and add a test that logs in with a non-empty guest cart.
  • "Atomic" is per-mutation, not per-request. The 4.1.0 transaction ensures a single mutation doesn't half-write, but two concurrent requests (double-click add) can still both succeed. For high-traffic carts, add a lock (Cache::lock("cart:{$user->id}")) or a unique constraint on (cart_id, buyable_id, options_hash).
  • Session driver + transactions don't mix. Session-backed carts can't be rolled back; the atomicity guarantee is real only for the database driver. Know which driver you're on before marketing atomicity to your team.
  • Options hashing. Cart line uniqueness usually depends on a hash of the options array. Array ordering and numeric-vs-string types in the options payload change the hash, producing duplicate lines. Normalize options (ksort) before mutating.
  • Money precision. Check whether the package stores integer minor units or floats; mixing the two in your own totals code causes cents drift. If it uses floats, wrap in a Money library at the boundary.
  • Cache/config traps. Run php artisan config:clear after editing cart.php; config:cache in production will mask config changes until you re-cache.
  • Extension points. Custom storage drivers, custom buyable resolution, and cart events (CartUpdated, item added/removed) are the intended hooks. Prefer listening to events over subclassing the manager — subclassing breaks on minor releases like this one.
  • Migration order. If you add a column to the cart items table, keep migrations additive; the package's own migrations run on install and re-running them after a version bump can conflict. Publish and rename your custom migrations.
  • Debugging. Dump Cart::content() and the active driver from config('cart.storage') first — most "cart is empty" reports are a driver mismatch between the web and queue/CLI contexts (no session in a job).
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource