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

Cart Shipping Laravel Package

elcodi/cart-shipping

Cart Shipping Component is part of the Elcodi e-commerce suite for Symfony, providing shipping calculation and cart shipping logic as a reusable PHP component under the MIT license. Read-only repository; use the main elcodi/elcodi package for issues and pull requests.

View on GitHub
Deep Wiki
Context7

Getting Started

This is an archived, read-only, end-of-life component (last release Feb 2016). Before writing any integration code, confirm two things:

  1. Your project is already pinned to a Symfony 2.x/3.x-era stack (the component predates Symfony 4+).
  2. You're comfortable vendoring or forking the source, since no PRs, issues, or fixes will be accepted upstream. File issues against elcodi/elcodi, not this repo.

Install

composer require elcodi/cart-shipping

If Composer struggles with abandoned metadata or version conflicts, add it as a VCS repository from your own fork, or copy the component source into src/ and register the namespace in composer.json (autoload.psr-4).

Where to look first

  • src/Elcodi/Component/CartShipping/ in the main elcodi/elcodi monorepo — the read-only split repo is a mirror.
  • In that folder, read Services/ first (the actual behavior), then Entity/ (the Cart ↔ ShippingMethod/Range link), then Factory/ and Resources/config/ (Doctrine mapping and service definitions).
  • Check src/Elcodi/Bundle/ in the monorepo to see how the component is wired into CartBundle/ShippingBundle. There may be no standalone CartShippingBundle, so treat the component as glue rather than a self-contained bundle.
  • The project docs at elcodi.io/docs may be dead; the most reliable usage examples are in the monorepo's test suites. Search the whole repo for CartShipping.

First use case

Attach a chosen shipping method/range to a cart and record its cost so it can be added to cart totals. Typical flow: customer selects a shipping option → you create a CartShipping from the factory → persist it → roll the amount into the cart's shipping total. Class names vary, but expect something close to:

$cartShipping = $cartShippingFactory->create();
$cartShipping
    ->setCart($cart)
    ->setShippingMethod($method)
    ->setShippingRange($range)
    ->setAmount($range->getPrice());

$cartShippingManager->save($cartShipping);
$cart->setShippingAmount($cartShipping->getAmount());
$cartManager->save($cart);

Implementation Patterns

1. Treat it as a link, not a calculator. Cost logic (weight bands, zones, free-shipping rules) belongs to the Shipping component and its ranges/rules. CartShipping persists which option the cart chose and what it costs. Don't put pricing logic here.

2. Recalculate on cart change. Hook into the Cart component's events (load/pre-load/change events, e.g. CartEvents::*) to re-resolve shipping whenever quantities, coupons, or addresses change:

class CartShippingRecalculator
{
    public function onCartChange(CartEvent $event)
    {
        $cart = $event->getCart();
        $cartShipping = $this->cartShippingRepository->findOneByCart($cart);
        if (!$cartShipping) {
            return;
        }
        // Re-resolve the range for the current cart state
        $amount = $this->shippingResolver->resolveAmount($cart, $cartShipping->getShippingMethod());
        $cartShipping->setAmount($amount);
        $this->cartShippingManager->save($cartShipping);
        $cart->setShippingAmount($amount);
    }
}

3. Decorate, don't fork. Old Elcodi services are named and public; you can override behavior without touching vendor code:

services:
    app.cart_shipping_manager:
        decorates: elcodi.cart_shipping_manager
        arguments: ['@app.cart_shipping_manager.inner']

Useful for adding free-shipping thresholds, logging, or forcing recalculation.

4. Custom shipping rules via the Shipping component. Implement the Shipping rule interface and register it; CartShipping will store the resulting range. Keep the custom rule and the cart persistence concerns separate.

5. Fixtures and tests with factories. The factory classes make it easy to build CartShipping objects in isolation. For integration tests, use KernelTestCase and the real manager/repository rather than mocking Doctrine.

6. Checkout orchestration. In your checkout flow, decide the order: resolve method → create/update CartShipping → recalculate cart totals → persist cart. Persisting in a different order is the most common source of stale totals.

Gotchas and Tips

  • EOL reality check. Archived since 2016, zero dependents, no security maintenance. Do not introduce it into new projects; use it only for legacy continuity. If you can't upgrade, plan to wrap it behind your own interface so you can swap it later.
  • PHP/Symfony drift. Expect issues on PHP 7.4+ and any Symfony 4+ project: old service visibility, deprecated event dispatcher signatures, dynamic properties. Budget for compatibility shims or pin the runtime.
  • Doctrine mapping is not auto-loaded. The component ships mapping files (likely YAML/XML) and a service definition but no bundle to register them. Add the mapping under doctrine.orm.mappings manually and verify the table name doesn't collide with your own shipping tables.
  • Duplicate rows. There's no guarantee of a unique constraint on cart_id. Enforce "one CartShipping per cart" in your manager — update the existing row instead of creating a new one on every selection.
  • Amounts and currency. Confirm whether amounts are integer minor units via the Currency/Money component. Mixing floats and integers there causes rounding bugs that are painful to trace.
  • Stale totals on cart mutation. Nothing automatically triggers recalculation when a line item changes — your event listener is the only thing keeping cart.shippingAmount correct. Log recalculations in dev to catch missed hooks.
  • Debugging. Dump the CartShipping entity alongside $cart->getShippingAmount() after each step; check Doctrine's unit of work if a changed amount isn't flushed. Old code often relies on explicit save() calls rather than cascade.
  • Symfony 4+ private services. If you're porting this into a newer app, service references in YAML may fail silently until you declare arguments explicitly; use bin/console debug:container to confirm wiring.
  • Docs may be gone. Prefer the monorepo's tests over any README or blog post — commit history and tests are the authoritative "documentation" for this package.
  • Escape hatch. If the integration proves heavier than the value it adds, reimplement the small piece (cart ↔ shipping option + amount) in your own domain. At this package's size and maturity level, that is often cheaper than resurrecting it.
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.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table