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 Manager Laravel Package

freshbitsweb/laravel-cart-manager

A Laravel package for adding shopping cart functionality to your app. It supports multiple carts, cart items, quantities, and totals, with a simple API and database migrations to persist carts and items. Easily integrate e-commerce cart features into any Laravel project.

View on GitHub
Deep Wiki
Context7

Getting Started

Pull the package in and publish its scaffolding:

composer require freshbitsweb/laravel-cart-manager
php artisan vendor:publish --provider="Freshbitsweb\LaravelCartManager\CartServiceProvider"
php artisan migrate

Publishing gives you a config/cart.php (tax rate, currency, formatting) plus migrations for the carts and cart_items tables. Look here first — the config file is where currency/tax behavior is decided, and the migrations tell you exactly what columns you get on CartItem (typically cart_id, cartable_id/cartable_type, quantity, price, tax, total, and a JSON attributes column).

Next, attach the trait to whatever model owns a cart — usually User:

use Freshbitsweb\LaravelCartManager\Traits\Cartable;

class User extends Authenticatable
{
    use Cartable;
}

Your first end-to-end use case is the classic "add a product, read the cart back":

$cart = auth()->user()->cart;          // default cart
$cart->add($product, 2, ['size' => 'M']);
$cart->add($accessory, 1);

$cart->items;                          // CartItem collection
$cart->total();                        // cart total
$cart->totalQuantity();                // item count

That is the whole loop for a minimal storefront: add, render items, show total, and delete. Everything else in this package is variations on that.

Implementation Patterns

Cart as a thin wrapper around Eloquent. The value of this package is that Cart/CartItem are real models you can query and eager-load. Lean into that instead of hiding them:

$cart = auth()->user()->cart()->with('items.cartable')->first();

foreach ($cart->items as $item) {
    $item->cartable;      // the Product (polymorphic)
    $item->quantity;
    $item->price;
    $item->attributes;    // cast to array
}

Item attributes for options. Pass variant data at add time and treat it as a snapshot:

$cart->add($product, $qty, [
    'size' => 'M',
    'color' => 'blue',
    'engraving' => 'A. Smith',
]);

The price and tax are captured when the line is added — good for price integrity, but it means the cart does not auto-follow catalog price changes.

Guest → user cart merge on login. The most common real-world requirement with a database cart. Keep a guest cart keyed by session, then on Login/Registered events merge it into $user->cart:

// In a listener
$guest = Cart::where('session_id', session()->getId())->first();
$userCart = $user->cart;

foreach ($guest->items as $item) {
    // De-duplicate on cartable + attributes if you want merged lines
    $userCart->add($item->cartable, $item->quantity, $item->attributes);
}
$guest->empty();

Multiple carts as named collections. Since the trait exposes cart() (default) and carts() (all), use them for wishlists and saved-for-later without a second schema:

$wishlist = $user->carts()->create(['name' => 'wishlist']); // verify columns shipped
$wishlist->add($product, 1);

// "move to cart"
$item = $wishlist->items()->findOrFail($id);
$user->cart->add($item->cartable, $item->quantity, $item->attributes);
$item->delete();

Wrap mutations in a service. Cart operations touch multiple rows and totals; putting them behind a small service (or CartManager-style class) keeps controllers thin and gives you one place to add locking, analytics, and coupon logic:

class CartService
{
    public function addToCart(Cart $cart, Model $product, int $qty, array $attrs = []): CartItem
    {
        return DB::transaction(function () use ($cart, $product, $qty, $attrs) {
            // look for existing line with same cartable + attributes first
            return $cart->add($product, $qty, $attrs);
        });
    }
}

Checkout = snapshot, not reuse. When an order is placed, copy cart_items into your own order_items table with price/tax/attributes frozen. Do not let the cart row become the order — the cart is mutable, the order must not be.

Presentation is a Blade partial. Render the cart once, reuse it on cart page, mini-cart, and checkout summary:

@foreach ($cart->items as $item)
    <tr>
        <td>{{ $item->cartable->name }}</td>
        <td>{{ $item->quantity }}</td>
        <td>{{ number_format($item->price, 2) }}</td>
        <td>{{ number_format($item->total, 2) }}</td>
    </tr>
@endforeach
<tr><td colspan="3">Total</td><td>{{ number_format($cart->total(), 2) }}</td></tr>

Gotchas and Tips

  • Prices/tax are captured at add time. Changing config/cart.php tax rate later does not retroactively fix existing cart items. If tax rules change, you need a recalculation pass over open carts. Plan for this before launch.
  • total() vs. formatted output. Check whether the installed version returns a numeric value or a formatted string — mixing the two into your own arithmetic is a classic source of "$19.99" + 5 bugs. Store and compute in raw decimals; format only at the view layer.
  • Rounding. Line-level tax rounding summed across many small items will drift from cart-level rounding. Decide one strategy (round per line, sum lines) and document it; the package will not reconcile this for you.
  • Polymorphic cartable has no FK. Deleting a product leaves orphaned cart_items rows with a dangling cartable_id. Add a cleanup job or observer on product deletion, and guard $item->cartable being null in the cart view.
  • Attributes are JSON. Great for options, terrible for querying. If you need "how many carts contain size M" reporting, promote those fields to real columns or a join table.
  • De-duplication is your job. add() may always create a new line rather than incrementing an existing matching line. If you want one row per product+variant, look up the existing CartItem (matching cartable and attributes) and updateQuantity instead.
  • Concurrency. Two tabs updating quantity can clobber each other. Wrap mutations in DB::transaction and consider lockForUpdate() on the cart item for anything money-touching.
  • N+1 on cartable. Always ->with('items.cartable') when rendering. A cart page with 20 lines and lazy loading is 21+ queries.
  • Guest vs. user carts. Sessions and user_id are two different lookup keys. Pick one resolution order (user cart if logged in, else session cart), put it in a single currentCart() helper, and never inline it in controllers.
  • Config caching. If you drive tax/currency from env, run php artisan config:clear after changing .env in dev; stale config is the usual "my tax rate didn't change" report.
  • empty() before deleting a cart. Clearing items through the package keeps totals and relations consistent; hard-deleting the Cart row may leave cart_items behind depending on the migration's cascade setup — check the published migration.
  • Verify method names against the installed version. This package was last released in early 2023; exact signatures (add, updateQuantity, remove, merge, empty) and the Cartable trait's relation names (cart, carts) are worth a five-minute read of vendor/freshbitsweb/laravel-cart-manager/src before you build services on top of them.
  • Extension points to use deliberately: publish the config, publish/override the models if you need extra columns, and hang your own events (CartItemAdded, CartMerged) around service methods rather than editing vendor code.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager