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

Commerce Bundle Laravel Package

vespolina/commerce-bundle

Vespolina Commerce Bundle brings e-commerce building blocks to Symfony applications, including product catalogs, carts, orders, pricing, and checkout workflows. It provides reusable commerce services and Doctrine-backed models for assembling flexible online stores.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check. vespolina/commerce-bundle is a Symfony 2 bundle, not a Laravel package. There is no service provider, no config/commerce.php, no facade. Its composer.json targets symfony/symfony ~2.x and PHP 5.x-era code, last tagged 2014-07-27, with 9 stars and 0 dependents. Running composer require vespolina/commerce-bundle inside a modern Laravel app will fail dependency resolution against illuminate/* and current symfony/* components. So "getting started" means one of two things:

  1. Read it as a domain-model reference (the realistic option), or
  2. Run it in a throwaway Symfony 2.8 / PHP 5.6–7.0 container, standalone, never next to Laravel.

Where to look first

Path Why
composer.json Confirms the Symfony 2 constraint and the vespolina/* library set (core, product, cart, order, pricing, taxation)
DependencyInjection/VespolinaCommerceExtension.php + Resources/config/services.xml The service graph and class parameters — the real "documentation" for this bundle
Model/ Cart, CartItem, Order, OrderItem, Product, Price — mostly plain PHP objects
Controller/CheckoutController.php + Checkout/ The checkout process and its ordered steps
Form/Type/, EventListener/ How forms and domain events were wired

First use case: port the cart/order model

The Model/ classes are largely POPOs with no Symfony coupling, so they PSR-4 fine inside Laravel:

// app/Domain/Commerce/CartItem.php  (ported from Vespolina\CommerceBundle\Model\CartItem)
class CartItem
{
    protected Product $product;
    protected int $quantity = 1;
    protected Price $unitPrice;   // snapshot, not a live product lookup
    protected ?Order $order = null;
}

Then give them persistence (Eloquent models wrapping the domain objects, or just Eloquent directly) and a CommerceServiceProvider that binds CartService, OrderService, PricingService interfaces. That's the fastest path to value from this repo.

Implementation Patterns

Managers → Laravel services

Vespolina delegated all mutation to managers (ProductManager, CartManager, OrderManager) configured as services with overridable class parameters. In Laravel, translate that shape to constructor-injected services bound in a provider:

$this->app->singleton(CartService::class, fn ($app) => new CartService(
    $app->make(CartRepository::class),
    $app->make(PricingService::class),
));

Keep the manager methods (addToCart, updateQuantity, findOpenCartFor, completeOrder) as the public API so the ported model code stays familiar.

Cart persistence

The Symfony bundle used a session-backed cart plus a cart identifier/provider. The Laravel equivalent that respects the same seam:

  • guest cart in the session (keyed by a UUID stored in the session),
  • merge into a DB cart on login (this merge step is where most bugs live — make it explicit and testable),
  • one CartProvider interface with SessionCartProvider and DatabaseCartProvider.

Checkout as a pipeline

The bundle's CheckoutProcess runs an ordered list of CheckoutSteps, each of which can validate and halt the flow. That maps cleanly onto Laravel:

// app/Checkout/CheckoutProcess.php
public function advance(Order $order, array $input): Order
{
    return app(Pipeline::class)
        ->send(new CheckoutContext($order, $input))
        ->through(config('commerce.checkout.steps'))  // [AddressStep, ShippingStep, PaymentStep, ReviewStep]
        ->then(fn (CheckoutContext $ctx) => $ctx->order);
}

Persist checkout_step on the order — never derive it from "what's filled in."

Domain events → Laravel events/observers

The bundle dispatched cart/order events to listeners for pricing, stock, email, and payment handoff. Mirror them:

  • CartUpdated → recalculate totals
  • OrderPlaced → invoice, email, stock decrement
  • OrderCompleted (post-payment) → fulfillment

Use queued listeners for anything touching payment or email so the checkout request stays fast.

Pricing and tax snapshots

Resolve price per product/option and tax per line item at the moment of adding to cart, and store the resolved unit price, tax rate, and tax amount on the line item. Display totals from stored values only. This is the single most important behavioural lesson in the package.

Templates are not portable

Resources/views/ is Twig with path(), render(controller(...)), and Symfony form themes. Rewrite Blade templates from scratch; don't attempt a conversion.

Gotchas and Tips

  • Not installable in Laravel. Composer will hard-conflict. Vendor/copy the code, or read it from a checkout of the repo. If you copy, keep the MIT copyright notice and LICENSE.
  • PHP 5-era syntax. Expect missing scalar type hints, array() notation, and possibly deprecated functions (each(), create_function()) that fatal or flood deprecations on PHP 8. Lint anything you copy before it enters app/.
  • Symfony DI XML quirks. Class swapping happened through container parameters (e.g. %vespolina_commerce.model.cart.class%), not autowiring. In Laravel this becomes interface bindings — don't try to mimic the parameter pattern, it buys you nothing.
  • ORM + PHPCR-ODM split. Products were often stored via Doctrine PHPCR-ODM (Jackalope) while carts/orders used the ORM, giving two entity managers and cross-store references by ID only. If you see Document/ and Entity/ side by side, that's why — and it's a common source of stale-product bugs. In a port, keep one store.
  • Money handling. Prices are value objects with a currency, but arithmetic in a 2014 codebase often touches floats. In your port use integer minor units and a single Money VO; don't port float math.
  • Rounding. Tax is computed per line item and then summed; line sums can drift from the order total if you recompute at the order level. Fix the rounding policy (per-line vs per-order) up front and test it.
  • Order state machine. Transitions are guarded and illegal transitions throw. Persist the state; make payment idempotent yourself, because the original flow assumes a single pass through the payment step.
  • Debugging. There is no maintained documentation and no meaningful test suite to lean on. Treat Resources/config/services.xml as the source of truth and grep for event dispatch sites to reconstruct behaviour.
  • Extension points, ranked by usefulness to you: (1) model classes — subclass or copy; (2) manager services — reimplement as Laravel services; (3) event subscribers — port to Laravel listeners; (4) checkout step registration — port to a pipeline config array.
  • Maintenance verdict. Abandoned since 2014, 9 stars, 0 dependents, no security patches, no PHP 8 support. Use it as a blueprint for commerce domain modelling (cart/order separation, price snapshots, step-based checkout, manager-per-aggregate). Do not use it as a dependency, and don't plan to "upgrade" it — reimplementing the model layer in Laravel is roughly a day of work and is the only sustainable path.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle