enhavo/shop-bundle
Enhavo Shop Bundle adds e-commerce functionality to the Enhavo CMS, an open-source PHP content management system built on Symfony and Sylius components. Distributed as a subtree split of the main Enhavo repository, it helps build flexible, complex data-driven shops with a clean, usable interface.
First, the framework reality check. This is not a Laravel package. There is no service provider, no config/shop.php, no auto-discovery entry, no Eloquent models. enhavo/shop-bundle is a Symfony bundle (a subtree split of the Enhavo CMS monorepo) built on Sylius components. If you are in a Laravel app, there is no "getting started" path here that is a sane use of time — you would be rebuilding Enhavo's resource/routing/block abstractions and Sylius's component wiring inside Laravel's container. Stop and evaluate sylius/* components directly, or a Laravel-native commerce option, instead.
If you are legitimately on Symfony (and ideally already on Enhavo), the minimal path is:
[READ-ONLY]; README is a logo and a pointer. Go to github.com/enhavo/enhavo, find the shop bundle directory, and read its composer.json, DependencyInjection/, Resources/config/, and Entity/ first. Those four places tell you the constraint matrix, the services, the routes, and the domain model — i.e. everything the split won't tell you.config/bundles.php alongside its Enhavo prerequisites (resource, routing, block, media, user/permission) — the shop bundle does not stand alone; it inherits that bundle graph.Budget a spike (days, not hours) just to get the container compiling with the right bundle set. If that compiles cleanly and the slice works, you have a foundation. If it fights you, treat that as the answer.
Resource-driven CRUD (the dominant pattern). Enhavo's resource abstraction is how the shop's entities are managed. Day-to-day this means you are not hand-writing controllers and admin screens for products and shop data — you declare a resource (entity class, form type, repository, routing) and Enhavo generates the admin CRUD around it. When you need a new shop-related admin entity, the idiomatic move is add a resource, not write a controller. Learn this pattern first; it is the single highest-leverage thing in the bundle.
Sylius components for domain, Enhavo for presentation. The split of responsibility is: Sylius components supply the commerce domain concepts (product, order, pricing, cart semantics), Enhavo supplies the CMS/admin/resource/Twig layer. So when a requirement is "how is price calculated," go to Sylius component source and configuration; when it's "how does an editor manage this in the admin," go to Enhavo resources. Keeping that line clear prevents you from hunting for pricing logic in the CMS layer or admin wiring in Sylius.
Content-coupled storefronts. The bundle's real value proposition is merchandising driven by editorial content: landing pages, lookbooks, campaign pages that surface products, rather than a pure catalog grid. The pattern is to build storefront pages as Enhavo content/block structures and reference shop entities from them, letting editors compose product-bearing pages in the CMS. Lean into this — it is where the bundle is differentiated and where the Sylius-components-without-full-Sylius footprint pays off.
Service overrides via the container. Because this is Symfony DI, integration tweaks happen through service decoration/overriding and parameters rather than config files. If you need custom pricing, a modified repository, or a decorated cart service, define your service in your app's services.yaml and decorate the Enhavo/Sylius service. This is the extension mechanism you'll reach for most; keep a running note of service IDs you override, because that list is your upgrade surface.
Template overrides. Storefront and admin rendering is Twig. Overriding templates (via bundle template precedence / your app's templates/bundles/... paths) is the standard way to adjust UI without forking the bundle. Do visual/logic changes in overridden templates and keep the bundle source pristine so upstream updates stay mergeable.
Keep a dependency register. Because the split lags the monorepo, record the mapping: your pinned parent release tag ↔ the split commit ↔ the Sylius component versions pulled. That mapping is the only reliable way to answer "what are we actually running" during upgrades or CVE triage.
composer require enhavo/shop-bundle in a Laravel app "just works" is wrong. Correct that assumption in writing before it propagates.[READ-ONLY]; the tracker is a dead end. Everything goes to github.com/enhavo/enhavo. Wire that into your team's contribution norms so people don't lose time on a mirror.How can I help you explore Laravel packages today?