excelwebzone/symfony-admin-bundle
SymfonyAdminBundle adds an admin backend to Symfony projects with common admin classes and services. Configure user, cron schedule, report, and file uploader services via YAML, then register the bundle routes to get started.
This is a Symfony bundle, not a Laravel package — the first decision point is whether your project is actually on Symfony (5/6/7 with autowiring and config/bundles.php). If you're on Laravel, stop here; there is no adapter path, and with 3 stars and 0 dependents you will be the only person maintaining a bridge.
Assuming Symfony:
composer require excelwebzone/symfony-admin-bundle, then add the bundle class to config/bundles.php. Check vendor/excelwebzone/symfony-admin-bundle/ for a Resources/config/routes.yaml or similar and import it if the admin UI is route-driven — the README doesn't tell you, so read the source before assuming a route prefix.user_repository, cron_schedule_repository, report_repository, and file_uploader, registered as services and named in config/packages/symfony_admin.yaml. Start with just user_repository and leave the rest commented out to see which ones are actually mandatory at container compile time.bin/console config:dump-reference symfony_admin is the real documentation here — it will show you the full tree for mime_types, timezone, and any keys the README truncated. Do this before writing the YAML.security.token_storage injection, and whatever templating/asset setup the bundle expects. Clear the cache and check bin/console debug:router for the admin entry point.Budget half a day for discovery. The README is a config snippet, not a guide; the source is the spec.
Adapter-style repositories. The bundle expects repositories shaped around Doctrine plus security.token_storage (per the example service definitions). Treat this as a contract you implement, not a base class you extend — write a thin adapter over your existing UserRepository that satisfies the bundle's interface and delegates. This keeps the bundle isolated to one file per concern and makes removal a one-commit operation.
app.user_repository:
class: App\Admin\Adapter\UserRepository
arguments: ['@doctrine', '@security.token_storage']
File uploader as a boundary. The example injects kernel, validator, translator, and %symfony_admin.mime_types...%. That means validation and translation live in the uploader, not the controller. Implement FileUploaderInterface-equivalent with a real target directory resolver (kernel.project_dir . '/public/' . $uploadUrl or a Flysystem mount), and let the bundle's mime type config drive your validation constraints rather than hardcoding extensions.
Timezone strategy. timezone.database and timezone.client are designed for the store-UTC, render-local pattern. Set both via env (APP_TIMEZONE_DATABASE=UTC, APP_TIMEZONE_CLIENT=Europe/London), persist in database timezone, convert at the repository or view-model layer. Don't let the admin UI be the only place this conversion happens or reports will disagree with the frontend.
Cron schedule as admin-managed state. The cron_schedule_repository implies schedules are rows, not code. Use it to let operators enable/disable/adjust cadence, but keep the actual job dispatch in your own Schedule/messenger layer reading those rows — never let the bundle be the thing that executes work.
Reports as dashboard widgets. report_repository maps naturally to a per-widget query object. Return scalars/series, keep the aggregation in your own query builder or DBAL, and let the bundle handle presentation.
Security. Wrap the admin routes in a firewall with a dedicated access_control entry requiring ROLE_ADMIN. Verify the bundle doesn't ship its own controller-level checks before relying on yours alone.
Testing. Because every collaborator is injected by service ID, you can swap in in-memory fakes (InMemoryUserRepository, a tmpdir uploader) in config/packages/test/symfony_admin.yaml and get full admin-controller coverage without a database.
composer.json ("excelwebzone/symfony-admin-bundle": "x.y.z"), commit composer.lock, and read CHANGELOG/GitHub releases before every bump. Last release date is recent relative to the bundle's age, but 3 stars suggests unreviewed code paths.symfony_admin.services.user_repository points at a typo'd or non-existent ID, you get a container compile error only on cache warm — not on composer require. Run bin/console cache:clear immediately after editing the YAML.services.yaml so config/packages/symfony_admin.yaml stays env-agnostic and diffable across environments.mime_types argument is truncated in the README. The parameter likely only exists once you've set symfony_admin.mime_types. If the uploader service fails to compile with an unresolved parameter, that's why — set the key explicitly or check the extension class for a default.%env()%. Define them in .env first, and give them defaults.security.token_storage in repositories makes them request-aware. If a cron command or messenger worker pulls one of these services, getToken() returns null in CLI and your repository may silently filter everything to "no user." Guard for null or use a separate CLI-facing service alias.upload_url is a relative path — resolve it against kernel.project_dir, not the web root, and confirm the directory is writable by the PHP user. Silent upload failures here look like validation errors.bin/console assets:install --symlink if the bundle ships Resources/public. A blank/unstyled admin page is usually this, not a routing problem.config:dump-reference symfony_admin → debug:container --parameter=symfony_admin.mime_types → debug:router → debug:event-dispatcher | grep -i admin. In that order; each answers a different class of "nothing renders."templates/bundles/SymfonyAdminBundle/, and adjust behaviour by decorating the bundle's services in services.yaml rather than forking. Since the project is small and unlikely to change fast, a fork is also defensible — but only if you vendor it as a path repository so the divergence is visible in review.How can I help you explore Laravel packages today?