Skip to main content

Overview

The cart page displays the items a customer has added to their cart, lets them adjust quantities or remove items, apply coupon codes, and review totals before proceeding to checkout. This guide walks through building a cart page using Lunar’s Lunar\Core\Models\Cart model and Lunar\Core\Facades\CartSession facade. The examples below use standard Laravel controllers and Blade templates. The same concepts apply whether the storefront is built with Livewire, Inertia, or a headless API.

Fetching the Current Cart

The CartSession facade retrieves the cart for the current session. Calling current() calculates totals (subtotal, tax, discounts, and so on) before returning the cart.
If no cart exists in the session, current() returns null. Handle this in the controller:
Cart prices are calculated on demand and are not stored on the cart lines. current() accepts a calculate argument (true by default) that runs the calculation pipeline before returning the cart. To force a recalculation after making changes, call $cart->recalculate().

Displaying Cart Lines

Each cart line holds a reference to a purchasable item (typically a Lunar\Core\Models\ProductVariant) along with the quantity and any custom metadata. After calculation, each line has computed properties for unit price, tax, discounts, and total.

Computed Properties on Cart Lines

After calculation, each Lunar\Core\Models\CartLine has the following properties: Every PriceValue wraps an integer minor-unit value and exposes format() (a formatted currency string) and decimal() (a float). Passing null values through Blade should be guarded with ?->format() where a property might not yet be calculated.

Accessing the Product from a Cart Line

The purchasable relationship on a cart line is polymorphic. For standard product variants:
The cart’s default eager loading (configured in config/lunar/cart.php) already loads lines.purchasable.product, lines.purchasable.values, and lines.purchasable.product.thumbnail, so these relationships are available without additional queries.

Updating Quantities

Use the updateLine() method on the cart to change a line’s quantity. This runs the configured validators (for example, stock checks) and recalculates the cart.
updateLine() also accepts an optional meta array for updating custom metadata on the line:

Validation Errors

When updating a line, Lunar runs the validators defined in config('lunar.cart.validators.update_cart_line'). If validation fails (for example, the requested quantity exceeds available stock), a Lunar\Core\Exceptions\Carts\CartException is thrown.

Removing Lines

Use the remove() method to delete a line from the cart.
To remove all lines at once, use clear():

Coupon Codes

Coupon codes are stored on the cart’s coupon_code field (automatically uppercased). When the cart recalculates, the discount pipeline checks whether the code matches any active discount and applies it.

Applying a Coupon

Checking discountTotal after recalculating is a heuristic, not a dedicated validation result: a code that matches a discount but yields no monetary reduction (for example, a free-item promotion) will look the same as an invalid code. Adjust the check to fit the discount types the store offers.

Removing a Coupon

Displaying Applied Discounts

After calculation, the cart provides a breakdown of all applied discounts:
Each entry in discountBreakdown is a Lunar\Core\ValueObjects\Cart\DiscountBreakdown, exposing price (a PriceValue), lines (the affected cart lines), and discount (the Lunar\Core\Models\Discount that was applied).

Cart Totals

After calculation, the cart provides all the totals needed to build a summary.

Computed Properties on the Cart

Tax Breakdown

To display a detailed tax breakdown (useful for stores with multiple tax rates):
Each entry is a Lunar\Core\ValueObjects\Cart\TaxBreakdownAmount with price, identifier, description, and percentage properties.

Estimated Shipping

Shipping costs are typically calculated during checkout once a full address is provided. However, the cart page can show an estimated shipping cost based on a partial address.
Passing setOverride: true tells the cart to use the returned shipping option when calculating totals for that request. The shippingTotal on the cart then reflects the estimate. When using CartSession, set the estimation parameters once and they persist for the session:

Routes

Putting It All Together

Here is a complete controller for the cart page:

Next Steps

  • Review the Carts reference for the full list of cart and cart line fields, configuration options, and session management.
  • Review the Extending Carts guide for customizing the cart calculation pipeline, adding validators, and overriding actions.
  • Review the Product Display Page guide for adding items to the cart from a product page.