modera/backend-tools-bundle
Modera Backend Tools Bundle is a PHP/Symfony bundle that equips admin backends with ready-made tooling: configurable grids and filters, CRUD scaffolding, forms, and UI helpers. It reduces boilerplate so teams can ship maintainable management panels faster.
Start by correcting the mental model: this is a Symfony bundle, not a Laravel package. There is no service provider, facade, publishable config, or Laravel-side install. For a Laravel developer, "getting started" means one of two paths:
Path A — you are in a legacy Modera/Symfony 2.8/3.x backend. Then:
composer require modera/backend-tools-bundle --dev
// app/AppKernel.php — order matters, the host panel must register first
new Modera\BackendBundle\ModeraBackendBundle(),
new Modera\BackendToolsBundle\ModeraBackendToolsBundle(),
# app/config/routing.yml — no auto-routing, you must import it manually
modera_backend_tools:
resource: "@ModeraBackendToolsBundle/Resources/config/routing.xml"
prefix: /backend
Read these in order, no detours:
Resources/config/routing.xml — the entire URL surface (typically a single /backend/tools entry).Controller/ToolsController.php — the actual tools. The surface is tiny (cache clear / environment info style actions), not a plugin system.Contributions/ — the menu-items provider. This is the real integration point and the thing that silently fails if mistagged.Resources/views/ — Twig templates you will end up overriding.First use case: render the backend menu item, click through to /backend/tools, confirm the action works. Then immediately wrap destructive actions (cache clear) behind a role check — see Gotchas.
Path B — you are on Laravel (the common case). Skip the install. Open the controller and template files as a specification for a native admin-tools page — a route group under your admin prefix, auth + can: middleware, Blade views, and Artisan commands behind destructive actions. Budget an afternoon for the read, not a sprint.
Menu contribution is not route discovery. The Tools section renders because a service implementing the backend's menu-items-provider interface is tagged and registered. Your mental model should be "menu is data, routes are separate." Adding a tool means adding both — a menu item and a route. One without the other gives you a dead link or an orphan page. This same split maps cleanly to Laravel: a navigation array in a view composer and a Route:: entry.
Extend without forking. In the Symfony case, register your own menu provider that returns the same tools section id, pointing at your own controller:
acme.backend.tools.menu:
class: Acme\AdminBundle\Contributions\ExtraToolsMenuProvider
tags:
- { name: modera_backend.menu_items_provider, priority: 10 }
Symfony merges menu items by section, so yours lands next to the built-ins. Do not edit vendor files — this bundle will never receive an upstream patch, so any edit is a permanent local fork.
Extract the action into a service. The cache-clear behaviour is the only genuinely reusable idea in the package. Pull it out of the controller into a maintainer service so the same code path is callable from a console command in your deploy pipeline — the backend button becomes a convenience, not the only way to do it. In Laravel terms: a small class (CacheMaintainer, LogRotator, SystemInfo) injected into both a controller and an Artisan command.
When porting to Laravel, mirror the shape, not the code. Map each Symfony concept to its Laravel equivalent:
| Symfony / Modera concept | Laravel equivalent |
|---|---|
Bundle registration in AppKernel |
Service provider + config publish |
| Menu-items-provider tag | Navigation array in a view composer / Filament resource |
isGranted() in controller |
can: middleware or Gate::authorize() |
| CSRF form token | @csrf + VerifyCsrfToken (automatic) |
| Console command alongside the action | Same service behind an Artisan command |
Gate everything by default. The bundle ships no opinionated ACL for its own actions. In a Modera app the backend firewall authenticates but authorisation for "clear the cache" is on you. The ported Laravel version should require a gate (admin or a dedicated ability) on every route in the group, not just the destructive ones — environment introspection is an information-disclosure vector too.
Audit the destructive ones. Cache flushes and log viewers executed by an admin session can degrade or disclose production state. Log who ran what, when, and from where. This is a few lines in the Laravel controller and is non-negotiable for anything that mutates shared state.
Abandonment is the headline gotcha. Last release 2016-06-10 — predates Symfony 4 entirely. Expect PHP 5.5–7.0 syntax, Symfony 2.8/3.x container APIs, annotation routing, sensio/framework-extra-bundle, and old Twig. It will not install on modern Symfony, and there is no security patching path. Treat the dependency itself as unusable; treat the source as reference material.
The [READ-ONLY] prefix means the split repo is not the development channel. Issues and PRs here go nowhere. Upstream lives in the Modera monorepo. If you need a fix, you either patch a fork you own or you do not get the fix.
Menu registration fails silently. If the menu item does not appear, the tag name is wrong or the provider is not registered on the container — the backend does not throw a useful error, it just omits the item. Debug by confirming the service is tagged (container dump) before chasing routes. This is the most common "it's installed but nothing shows" failure.
Routing must be imported explicitly. No auto-discovery. If the menu item appears but 404s on click, the routing.yml import is missing or the prefix is wrong.
No CSRF opinions on the built-in actions. The 2016-era code predates the current framework's defaults in spirit, if not in fact. Any ported version must add CSRF protection — in Laravel, VerifyCsrfToken covers you provided the actions go through forms rather than raw GET links.
Version drift between ModeraBackendBundle and this bundle causes container-compile failures and menu/route registration collisions. There are no constraints to speak of, and nothing to pin against. If you must run it, pin every Modera bundle to a known-good combination and expect to own that lockfile forever.
Do not vendor the original into Laravel. A partial port of Symfony 2-era code buys you the vulnerabilities without the maintenance. Rewrite the small surface natively — it is roughly 50 lines on the Laravel side (route group, middleware, a Blade view, one or two service classes, matching Artisan commands).
Extension points worth stealing for your own implementation:
Record the decision. Zero stars, zero dependents, zero releases in ~a decade. Write down "evaluated, not adopted, do not resurface in dependency scans" so the next audit does not pay the 2–4 engineer-day discovery cost again.
How can I help you explore Laravel packages today?