mrdanshur/user-bundle
mrdanshur/user-bundle is a Laravel package that provides a ready-made user management layer, including authentication scaffolding, profile handling, and role-based access helpers. It aims to speed up adding users, permissions, and account features to new or existing PHP applications.
First, recalibrate: mrdanshur/user-bundle is a fork of FOSUserBundle, a Symfony bundle — not a Laravel package. There is no service provider, no config/user-bundle.php, no Blade views. Day-to-day, you only touch this if you're maintaining a Symfony app (or a Symfony/Laravel hybrid where the user store lives on the Symfony side). The Laravel mental model still maps roughly:
| Laravel | This bundle |
|---|---|
composer require + auto-discovery |
composer require + manual config/bundles.php entry |
config/auth.php |
config/packages/security.yaml + config/packages/fos_user.yaml |
Eloquent User model |
Doctrine entity extending FOS\UserBundle\Model\User |
| Breeze/Fortify controllers | Built-in registration/login/reset/profile controllers |
Blade overrides via vendor:publish |
Twig overrides via templates/bundles/FOSUserBundle/ |
Minimal path to first working login:
composer require mrdanshur/user-bundle — then immediately open the fork's composer.json. Confirm the PSR-4 namespace is still FOS\UserBundle\, check the symfony/* and php constraints, and see whether mail goes through Swiftmailer or symfony/mailer. This one file determines whether the package is usable at all on your Symfony version.FOS\UserBundle\FOSUserBundle::class => ['all' => true] in config/bundles.php.src/Entity/User.php extending FOS\UserBundle\Model\User and add Doctrine mapping (@ORM\Entity / attributes). Add id and any extra columns.config/packages/fos_user.yaml: db_driver: orm, firewall_name: main, user_class: App\Entity\User, from_email: [email protected].config/packages/security.yaml: provider fos_userbundle: { id: fos_user.user_provider.username_email }, form_login with check_path: fos_user_security_check, user_checker: fos_user.user_checker.fos_user_security, fos_user_registration, fos_user_resetting, fos_user_profile, fos_user_change_password.bin/console doctrine:schema:update --force (or a migration), then hit /register and /login.First real use case: dropping registration + login + password reset + profile editing into an existing Symfony admin app so you don't hand-roll token generation, confirmation emails, and password hashing.
Extending the user entity. Add domain fields to your User class, not the bundle's. Override getRoles() carefully — FOSUserBundle merges roles and groups and will silently return ROLE_USER only if you forget to call parent::getRoles(). Generate migrations with doctrine:migrations:diff rather than schema update once you have real data.
Programmatic user creation. Inject fos_user.user_manager (FOS\UserBundle\Model\UserManagerInterface) wherever you need it — seeders, imports, API endpoints:
$user = $this->userManager->createUser();
$user->setUsername($name)->setEmail($email)->setPlainPassword($pw)->setEnabled(true);
$this->userManager->updateUser($user);
Note setPlainPassword + updateUser is what triggers hashing; setPassword writes a raw hash and will lock the account. findUserByEmail(), findUserByUsername(), and findUsers() cover most lookups.
Overriding without forking controllers. Subclass a bundle controller, point a route at your subclass, and override only the method you need (registerAction, resetAction). For view-only changes, drop Twig files into templates/bundles/FOSUserBundle/Registration/register.html.twig etc. — no config needed.
Event subscribers are the extension point you'll actually use. Hook FOSUserEvents::REGISTRATION_CONFIRM to provision a tenant, REGISTRATION_SUCCESS to push to your CRM, RESETTING_RESET_SUCCESS to invalidate API tokens, SECURITY_IMPLICIT_LOGIN to stamp last_login_at. This is the cleanest place for side effects and avoids overriding controllers at all.
CLI for ops. fos:user:create, fos:user:promote, fos:user:demote, fos:user:activate, fos:user:change-password are genuinely useful in day-to-day support work — worth documenting for your team before you write any admin UI.
API surfaces. Don't reuse the HTML controllers for a JSON API. Use UserManagerInterface plus your own authenticator/guard and keep the bundle for storage and password semantics only. If you also need confirmation emails, call fos_user.mailer explicitly.
Testing. Load fixtures through the user manager so passwords are hashed correctly, and assert against $client->getContainer()->get('fos_user.user_manager').
make:user + make:auth (or a maintained auth bundle) instead. On a legacy app, pin the version and vendor-fork if needed.fos_user.mailer built on Swiftmailer, removed from Symfony in 6.0. If composer.json requires swiftmailer/swiftmailer, you'll need a decorator around fos_user.mailer or a shim before upgrading. Check this before anything else.from_email unset = silent registration failure. The confirmation mail throws, often after the user row is written. Set fos_user.from_email and fos_user.registration.confirmation.from_email.confirmation.enabled: true and broken mail, users exist but can't log in. fos:user:activate <username> unsticks them; add it to your runbook.security.encoders; Symfony 5.3+ renamed to password_hashers. If login always fails with correct credentials, this mismatch is the first thing to check.user_class drift. A typo or a stale cache (bin/console cache:clear) gives you a provider that queries the wrong table and reports "Bad credentials" forever.fos_user_security before any catch-all/localized route, or /login gets swallowed.fos_user.resetting.token_ttl is in seconds (default 86400) and retry_ttl throttles re-requests; both trip people up during QA.templates/bundles/FOSUserBundle/, not the Symfony 3 app/Resources/ location — a 2021 fork will not look in the old place.bin/console debug:container fos_user, debug:router | grep fos_user, debug:event-dispatcher FOSUserEvents.fos_user.util.token_generator (shorter/URL-safe tokens), decorate fos_user.mailer (swap transport), and lean on FOSUserEvents constants rather than overriding controllers.How can I help you explore Laravel packages today?