Install User Bundle
This guide covers the practical minimum to get the bundle running in a real application.
At the end of this guide you will have:
- a concrete
App\Entity\User - the bundle enabled
- routes imported
- Symfony Security configured
- a first admin user created from CLI
Install The Package
composer require softspring/user-bundle:^6.0
If your application does not use Symfony Flex, enable the bundle manually:
<?php
return [
// ...
Softspring\UserBundle\SfsUserBundle::class => ['all' => true],
];
What The Flex Recipe Adds
With Symfony Flex, the recipe gives you a practical starting point:
src/Entity/User.phpconfig/routes/sfs_user.yamlconfig/routes/admin/sfs_user.yamlconfig/packages/sfs_user.yamlconfig/packages/security.yaml.dist
Some features stay disabled or commented on purpose:
- public register
- invitations
- access history
That default is intentional. Invitations and access history need extra concrete entities and should not be enabled accidentally in a fresh install.
Create Your User Entity
The bundle is designed to work with your own concrete User class.
The usual pattern is:
- extend
Softspring\UserBundle\Model\User - implement only the interfaces you need
- compose the matching traits
A practical baseline for many projects is:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Softspring\UserBundle\Entity\ConfirmableTrait;
use Softspring\UserBundle\Entity\NameSurnameTrait;
use Softspring\UserBundle\Entity\PasswordRequestTrait;
use Softspring\UserBundle\Entity\RolesAdminTrait;
use Softspring\UserBundle\Entity\UserHasLocalePreferenceTrait;
use Softspring\UserBundle\Entity\UserIdentifierEmailTrait;
use Softspring\UserBundle\Entity\UserLastLoginTrait;
use Softspring\UserBundle\Entity\UserPasswordTrait;
use Softspring\UserBundle\Model\ConfirmableInterface;
use Softspring\UserBundle\Model\NameSurnameInterface;
use Softspring\UserBundle\Model\PasswordRequestInterface;
use Softspring\UserBundle\Model\RolesAdminInterface;
use Softspring\UserBundle\Model\User as UserModel;
use Softspring\UserBundle\Model\UserHasLocalePreferenceInterface;
use Softspring\UserBundle\Model\UserIdentifierEmailInterface;
use Softspring\UserBundle\Model\UserLastLoginInterface;
use Softspring\UserBundle\Model\UserPasswordInterface;
#[ORM\Entity]
#[ORM\HasLifecycleCallbacks]
class User extends UserModel implements
NameSurnameInterface,
UserPasswordInterface,
PasswordRequestInterface,
UserIdentifierEmailInterface,
ConfirmableInterface,
RolesAdminInterface,
UserLastLoginInterface,
UserHasLocalePreferenceInterface
{
use UserIdentifierEmailTrait;
use NameSurnameTrait;
use UserPasswordTrait;
use PasswordRequestTrait;
use ConfirmableTrait;
use RolesAdminTrait;
use UserLastLoginTrait;
use UserHasLocalePreferenceTrait;
#[ORM\Id]
#[ORM\Column(length: 13, options: ['fixed' => true])]
#[ORM\GeneratedValue(strategy: 'NONE')]
protected ?string $id = null;
#[ORM\PrePersist]
public function generateId(): void
{
$this->id = uniqid();
}
public function getId(): ?string
{
return $this->id;
}
public function getDisplayName(): string
{
return trim(($this->getName() ?? '').' '.($this->getSurname() ?? ''));
}
}
This baseline gives you:
- email-based login
- encoded passwords
- admin and super-admin flags
- email confirmation
- reset password
- last login storage
- locale preference
Configure The Bundle
Minimal config:
# config/packages/sfs_user.yaml
sfs_user:
class: App\Entity\User
Recommended starter config:
# config/packages/sfs_user.yaml
imports:
- { resource: '@SfsUserBundle/config/security/admin_role_hierarchy.yaml' }
sfs_user:
class: App\Entity\User
confirm_email:
enabled: true
reset_password:
token_ttl: 86400
login:
target_path_parameter: _target_path
invite:
enabled: false
history:
enabled: false
Important options:
class: your concrete user entityentity_manager: Doctrine entity manager nameconfirm_email.enabled: enable or disable the confirmation email flowreset_password.token_ttl: password reset token lifetime in secondslogin.target_path_parameter: query or form parameter used for redirect-after-logininvite.enabled: enables invitation services and routeshistory.enabled: enables access history services and routes
Import Routes
Import the route groups in your main config/routes.yaml:
_sfs_user:
resource: 'routes/sfs_user.yaml'
prefix: '/app'
_sfs_admin_user:
resource: 'routes/admin/sfs_user.yaml'
prefix: '/admin/users'
Then create the public routes file:
# config/routes/sfs_user.yaml
_sfs_login:
resource: '@SfsUserBundle/config/routing/login.yaml'
_sfs_reset_password:
resource: '@SfsUserBundle/config/routing/reset_password.yaml'
prefix: '/reset-password'
_sfs_change_password:
resource: '@SfsUserBundle/config/routing/change_password.yaml'
prefix: '/user/change-password'
_sfs_preferences:
resource: '@SfsUserBundle/config/routing/preferences.yaml'
prefix: '/user/preferences'
#_sfs_register:
# resource: '@SfsUserBundle/config/routing/register.yaml'
# prefix: '/register'
This matches the default Flex recipe.
Start with login, reset password, preferences, and change password. Add the optional route groups only when the project needs them:
register.yamlfor self-service signupinvitation.yamlfor invitation-only onboardingchange_email.yaml,change_username.yaml, andsettings_confirmation.yamlfor extra self-service pages
And the admin routes file:
# config/routes/admin/sfs_user.yaml
_sfs_user_admin:
resource: '@SfsUserBundle/config/routing/admin_users.yaml'
prefix: '/user'
_sfs_user_admins:
resource: '@SfsUserBundle/config/routing/admin_administrators.yaml'
prefix: '/admins'
#_sfs_user_invitations:
# resource: '@SfsUserBundle/config/routing/admin_invitations.yaml'
# prefix: '/invitations'
#_sfs_user_history:
# resource: '@SfsUserBundle/config/routing/admin_access_history.yaml'
# prefix: '/access-history'
Keep invitations and access history commented until the related sfs_user feature flags and concrete entities exist.
The bundle is modular. Import only the route groups you actually want to expose.
Configure Symfony Security
The bundle expects a provider based on sfs_user.user_provider.
Use a base security config like this:
# config/packages/security.yaml
security:
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
providers:
sfs_user:
id: sfs_user.user_provider
access_decision_manager:
strategy: unanimous
allow_if_all_abstain: false
role_hierarchy:
ROLE_ADMIN:
- ROLE_SFS_USER_ADMIN_USERS_RW
- ROLE_SFS_USER_ADMIN_ADMINISTRATORS_RW
ROLE_SUPER_ADMIN:
- ROLE_ADMIN
- PERMISSION_SFS_USER_ADMIN_ADMINISTRATORS_PROMOTE_SUPER
- PERMISSION_SFS_USER_ADMIN_ADMINISTRATORS_DEMOTE_SUPER
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/(admin|app)/
lazy: true
provider: sfs_user
form_login:
provider: sfs_user
login_path: sfs_user_login
check_path: sfs_user_login_check
logout:
path: sfs_user_logout
access_control:
- { path: ^/app/login, roles: PUBLIC_ACCESS }
- { path: ^/app/reset-password, roles: PUBLIC_ACCESS }
- { path: ^/admin, roles: ROLE_ADMIN }
If you enable registration or invitations later, open those public routes explicitly in access_control.
Run Doctrine Migrations
Once your User entity exists and the bundle config is in place, create and run migrations:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate -n
Create The First Admin User
The bundle ships CLI commands for the first bootstrap:
php bin/console sfs:user:create admin admin@example.com ChangeMe --enabled --admin
php bin/console sfs:user:promote admin --super-admin
Main commands:
sfs:user:createsfs:user:promotesfs:user:invite
Real Integration Pattern
In armonic-standalone, the bundle is usually integrated with:
- public app routes under
/app - admin routes under
/admin/users - imported admin role hierarchy
- a single
mainfirewall for/appand/admin
That is a good reference when you want a real project example instead of an isolated snippet.
Related Guides
- Login and security for the full firewall, target path, remember me, and switch user setup.
- Register and reset password if your application is public and users can create their own accounts.
- Admin area to wire the backoffice screens after the base install is done.
- Invitations and access history if you need invitation-only onboarding or login audit trails.