runroom-packages/user-bundle
A Symfony bundle from Runroom that streamlines user management by providing reusable user entities, services, and configuration for accounts, authentication, and profiles, helping you add consistent, maintainable user handling to your Symfony applications with minimal setup and boilerplate.
This is a Symfony bundle, not a Laravel package — it has no service provider, no config/user-bundle.php, and no Artisan commands. Before you invest time, confirm your stack is Symfony + Sonata Admin + Sonata UserBundle + Doctrine ORM. If you are on Laravel, stop here; the effort to port it outweighs rewriting the ~20 lines of "admin user + roles" it saves.
Assuming a Symfony app:
composer require runroom-packages/user-bundle
config/bundles.php:
Runroom\Packages\UserBundle\RunroomUserBundle::class => ['all' => true],
sonata-project/admin-bundle, sonata-project/user-bundle, sonata-project/doctrine-orm-admin-bundle, and symfony/security-bundle are already wired up. Do that before touching this bundle or you will chase mapping errors.AdminUser base class; you own the concrete entity in src/Entity/AdminUser.php (or equivalent) and point Doctrine at it.config/packages/runroom_user.yaml with your entity class, manager class, and table name.bin/console make:migration && bin/console doctrine:migrations:migrate (or doctrine:schema:update --force in dev)./admin with a user created via bin/console sonata:user:create or a fixture.Where to look first:
vendor/runroom-packages/user-bundle/src/Entity/ — the base class you'll extendvendor/runroom-packages/user-bundle/src/Manager/ — the user manager servicevendor/runroom-packages/user-bundle/src/Admin/ — Sonata admin classesconfig/packages/security.yaml — your firewall must use the Sonata user providerconfig/packages/sonata_user.yaml — the class key must match your entityExtending the base entity. You almost never use the bundle's entity directly. Subclass it, add your fields, and register the subclass in both this bundle's config and sonata_user.yaml:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Runroom\Packages\UserBundle\Entity\AdminUser as BaseAdminUser;
#[ORM\Entity(repositoryClass: AdminUserRepository::class)]
#[ORM\Table(name: 'admin_user')]
class AdminUser extends BaseAdminUser
{
#[ORM\Column(type: 'string', length: 100, nullable: true)]
private ?string $displayName = null;
}
Overriding the admin class. The bundle exposes a Sonata Admin service for users. Re-declare it in config/services.yaml with your own class (or extend the bundle's) to add/remove form fields, list columns, and filters. Register the service with the sonata.admin tag:
App\Admin\AdminUserAdmin:
arguments:
- ~
- App\Entity\AdminUser
- ~
tags:
- { name: sonata.admin, manager_type: orm, label: 'Admin users' }
Using the manager instead of the repository. Day-to-day user creation should go through the bundle's user manager (it handles password encoding and role normalization):
$manager->createWithPassword($user, $plainPassword);
$manager->save($user);
// or
$manager->findOneByEmail($email);
Adding roles. Use Sonata's role hierarchy in config/packages/security.yaml rather than hard-coding ROLE_ADMIN strings; the bundle reads roles from the user entity but does not manage the hierarchy.
Fixtures / seed data. Do not rely on the bundle for fixtures. Write a normal Doctrine fixture that calls the user manager — this is the pattern that survives composer updates.
Password reset. If the bundle wires a reset flow, verify it against your mailer config; otherwise use Sonata's built-in sonata:user:reset-password command.
Integration tip: keep the firewall explicit. Point the Sonata admin firewall at your AdminUser entity's provider, and load the provider from the entity's email field. Do not reuse a users provider used for front-end customers.
php artisan, no .env conventions, no facades. If the evaluation is "should we pull this into a Laravel app?" — no. It requires Symfony Kernel, DependencyInjection, and Sonata.composer.json and be prepared to vendor a fork if it breaks against a new Sonata release.composer.json constraints against your lockfile before installing.#[ORM\MappedSuperclass] on your abstract intermediate class, and (b) two entities mapping to the same table name. Set the table in your subclass only.bin/console doctrine:schema:validate after every entity change, not just schema:update.bin/console cache:clear — otherwise the container serves stale class references and you get "entity not mapped" exceptions.bin/console debug:container | grep -i user
bin/console debug:config runroom_user
bin/console debug:router | grep -i sonata
admin firewall must come before the main firewall in security.yaml, and must use form_login with the Sonata admin login check path, or you get redirect loops.security.yaml verifies with another, login silently fails. Both must reference the same App\Entity\AdminUser.src/Entity, src/Manager, and src/Admin. Anything beyond subclassing and re-tagging services is a fork. Prefer extending and overriding over editing vendor code./admin/login and a functional test that authenticates; the bundle ships almost no tests, so regressions after a Sonata bump will surface in your app first.How can I help you explore Laravel packages today?