softspring/cms-bundle
Softspring CMS Bundle is a flexible content management bundle for Symfony apps, offering page management, reusable content blocks, menus, and an extensible admin interface to help teams build and maintain websites faster.
First, set expectations: softspring/cms-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no config/app.php, no Artisan. If you're coming from Laravel, map the concepts: bundle registration → config/bundles.php, package config → config/packages/softspring_cms.yaml, publishable views → Twig template overrides under templates/bundles/SoftspringCmsBundle/.
Install and wire up:
composer require softspring/cms-bundle
config/bundles.php (Flex recipes usually do this for you).config/routes/softspring_cms.yaml) so site/module front-end and admin routes are reachable.bin/console doctrine:schema:update --dump-sql (or a migration) to confirm the CMS tables exist.bin/console debug:container | grep softspring_cms and bin/console debug:router | grep cms to see what actually got registered — this is the fastest way to learn the package's surface area.Look here first: the site resolution layer (the listener/middleware that turns an incoming request into a "current CMS site"), the Doctrine mappings for Site/Module/Page, and the admin controllers. Those three define 90% of day-to-day behaviour.
First real use case: create one CMS site, attach a module, create a page, and render it through the bundle's front controller. Once that works end-to-end, add a second site on a different host/locale and confirm the resolver picks the right one.
v5.6.0 specifically adds disabled CMS sites. So your first experiment should include flipping a site to disabled and verifying: front-end returns 404/410 as configured, admin still renders, and the site doesn't leak into menus, sitemaps, or hreflang.
Multi-site as the primary abstraction. Model each site as a first-class record with host/locale and its own module tree. Keep environment-specific sites (staging, internal preview, per-client microsites) as separate site records rather than config forks — that's the pattern the disabled flag in v5.6.0 is designed to support.
Use the disabled flag instead of deletion. The obvious workflow unlocked by v5.6.0: a site under construction or a seasonal microsite goes disabled rather than being removed. This preserves content, redirects, and IDs so re-enabling later doesn't churn URLs. Pair it with your own convention — e.g. an enabledAt/disabledAt column or a status enum wrapper — so you get an audit trail.
Preview vs. public access. A common integration is: disabled site → public requests 404, but requests carrying an authenticated admin session (or a signed preview token) resolve normally. Implement this by decorating the site resolver/listener rather than editing vendor code, so the check is centralised and testable.
Admin UI: extend the built-in module modal, don't reimplement it. The v5.6.0 fix for the module modal transition race implies the admin JS owns modal lifecycle events. If you've added custom buttons, duplicate form submissions, or extra modal triggers, attach behaviour via the events the bundle dispatches rather than binding your own click/submit handlers — that's how the race appeared in the first place.
Configuration over decoration. Start with config/packages/softspring_cms.yaml (site defaults, module registration, routing prefixes, caching). Only move to service decoration/compiler passes when config genuinely can't express the need.
Testing pattern. Functional tests are the right level: assert route X resolves to site A's page, assert a disabled site returns the expected status on the front end, and assert the admin module list still loads with a disabled site present.
softspring/cms-bundle laravel docs, php artisan vendor:publish, or a service provider. Everything is Symfony DI, events, and Twig.disabled semantics before trusting them. "Support disabled CMS sites" is a new behaviour. Check explicitly: front-end status code, admin visibility, sitemap inclusion, menu/Twig helper output, cache warmer behaviour, and whether a disabled site can still be resolved as a fallback for unmatched hosts. Write these down as tests as soon as you upgrade — the semantics may shift in 5.7.bin/console cache:clear is not optional for a bundle that introduces new config keys, and admin JS changes require re-publishing/rebuilding assets. A stale asset manifest is the most likely cause of "the modal fix didn't apply".doctrine:schema:update --dump-sql first and turn it into an explicit migration.templates/bundles/SoftspringCmsBundle/, and service decoration of the site resolver. Prefer these over forking — v5.6.0 is a patch-level release, but the two lines changed (modal transitions, site disabled state) are exactly the areas you'd least want to have hard-coded assumptions against.How can I help you explore Laravel packages today?