liverbool/dos-theme-bundle
A Symfony bundle that packages theme templates and assets so you can apply a consistent look across your application. Configure themes in one place, then reuse them in controllers and Twig views without duplicating styling code.
First, calibrate expectations: liverbool/dos-theme-bundle is a Symfony bundle, not a Laravel package. It targets the Symfony 2.x/3.x era (last release January 2016), so you will not composer require it into a Laravel app and get a service provider. Treat this assessment as “what the package does and whether the ideas transfer,” not “how to install it in Laravel.”
Minimal steps if you were evaluating it in its native habitat:
composer.json — confirm the symfony/framework-bundle, symfony/twig-bundle, and PHP constraints. These tell you immediately whether it can run on anything modern.README.md and Resources/config/ — the service definitions reveal the core abstractions (typically a theme manager, a theme resolver, and a Twig loader/path injector).DependencyInjection/ — the extension class shows the actual config tree: theme directories, default theme, fallback order.AppKernel (Symfony 2/3 only) and add a dos_theme: config block pointing at a theme directory under Resources/themes or app/Resources/themes.index.html.twig, set it as active via config, and render that template from a controller to confirm the loader override works.For a Laravel developer, the “first use case” worth copying is the concept: a config-driven active theme plus a fallback chain, resolved before view rendering. You can build that in Laravel in an afternoon with View::addNamespace() and a view composer — see below.
The bundle’s architecture follows the classic Symfony theme pattern; the patterns below are what you would replicate or integrate.
Theme resolution. Typically a ThemeResolver reads the active theme from config, request attributes, session, or a cookie. In a Laravel port you would implement a ThemeResolver contract with drivers (config, session, domain) and bind it as a singleton. Resolve once per request in a middleware and stash the theme name on the request or in a container binding.
Template override / inheritance. The bundle injects theme paths into Twig’s loader ahead of the default paths. In Laravel the equivalent is:
// In a service provider
View::addNamespace('theme', base_path('themes/'.config('theme.active')));
View::addLocation(base_path('themes/'.config('theme.active').'/views'));
Then fall back explicitly: try theme::home, catch the missing-view exception, and render pages.home. A dedicated ThemeViewFinder that wraps Laravel’s finder is cleaner than try/catch in controllers.
Fallback chain. The bundle supports a default theme plus the active one. Model this as an ordered array in config/theme.php:
'fallbacks' => [env('THEME'), 'shared', 'default'],
Resolve the first theme directory that contains the requested view. This is the single most useful idea in the package.
Asset handling. Old Symfony theme bundles often publish theme assets to web/. In Laravel, prefer Vite or a theme_asset() helper that prefixes themes/{active}/assets/. Avoid copying assets into public/ per theme; it drifts.
Integration points. The bundle exposes a manager service; in Symfony you would inject it into controllers and Twig globals. In Laravel, register a Theme facade and share theme.name and theme.asset_path as view globals via View::share().
Workflow tip. Keep theme directories out of resources/views. Use themes/{name}/{views,assets,config} so a theme is a self-contained, deployable unit — the bundle’s directory convention is the part worth preserving.
It is dead code. Last release 2016, zero stars, zero dependents. It predates Symfony 4’s bundle-less app structure and Flex. Do not plan a production dependency on it; there is no maintenance path for PHP 8 or Symfony 6/7.
Not Laravel-compatible. There is no ServiceProvider, no Illuminate\Contracts bindings, and the code assumes Symfony’s HttpKernel, DependencyInjection, and TwigBundle. Porting means rewriting the DI wiring entirely — you are really just borrowing the design.
Template locator order is the usual bug. When a theme “doesn’t apply,” it is almost always loader precedence: the default Twig path is still ahead of the theme path. In Symfony, debug with debug:twig / twig:lint; in a Laravel port, View::getFinder()->getPaths() and getHints() tell you the real order.
Cache invalidation. Symfony’s container and Twig caches hide config changes. Clear var/cache after changing theme config. Laravel equivalent: php artisan view:clear and config:clear whenever the active theme is toggled.
Config quirks. Old bundles tend to require absolute paths or paths relative to the kernel root, and silently fall back to a default theme when a path is missing. Validate the theme directory exists at boot and fail loudly rather than rendering the default theme — silent fallback is the source of “why is my theme ignored?” tickets.
Extension points. The realistic places to hook are the theme resolver (swap resolution strategy) and the loader (add paths). Both are easy to reimplement; do that rather than subclassing bundle internals.
Debugging checklist. (1) Is the bundle/service registered? (2) Is the theme directory path correct and readable? (3) Is the resolver returning the expected name? (4) Is the loader order correct? (5) Is the cache stale? This covers nearly every failure mode.
Recommendation for Laravel teams. Skip the package. Implement the pattern natively: a ThemeManager singleton, a ResolveTheme middleware, a ThemeViewFinder with an ordered fallback list, a theme_asset() helper, and a theme:make artisan command to scaffold directories. You get the useful 10% of this bundle with none of the 2016 Symfony baggage.
How can I help you explore Laravel packages today?