Reputation: 681
Version : Symfony 2.2
I'm trying to add a default role when a user register on my website. I use FOSUserBundle and i see that when a user register the role field is empty in a database. I begin with this huge bundle and it's not very easy to understand. So i read all the documentation and i'm not sur what to do.
For now, i create an Event to add this role dynamically, but it doesn't work (i have no error but my database is still empty) I'm not even sur this is the good way to do that ?
My Event :
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class AddDefaultRoleListener implements EventSubscriberInterface {
private $container;
public function __construct(Container $container)
{
$this->container = $container;
}
/**
* {@inheritDoc}
*/
public static function getSubscribedEvents()
{
return array(
FOSUserEvents::REGISTRATION_SUCCESS => 'onAddDefaultRoleSuccess',
);
}
public function onAddDefaultRoleSuccess(FormEvent $event)
{
$doctrine = $this->container->get('doctrine');
$em = $doctrine->getManager();
$user = $event->getForm()->getData();
$user->addRole('ROLE_USER');
//$user->setRoles(array('ROLE_USER'));
$em->persist($user);
}
}
As you see i create a simple event which listen on REGISTRATION_SUCCESS, but nothing seems to work. It's my first try with Events and services. So if someone has an advice, i'll take it :)
Upvotes: 26
Views: 36778
Reputation: 2776
You can add an Event Subscriber to a Form Class and use the form event "formEvents::POST_SUBMIT"
<?php
//src/yourNS/UserBundle/Form/Type/RegistrationFormType.php
use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
use yourNS\UserBundle\Form\EventListener\AddRoleFieldSubscriber;
class RegistrationFormType extends BaseType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
// add your custom field
$builder->add('firstName')
->add('lastName')
->add('address')
//...
//...
->add('phone');
$builder->addEventSubscriber(new AddRoleFieldSubscriber());
}
public function getName()
{
return 'yourNS_user_registration';
}
}
Now the logic for adding the role field resides in it own subscriber class
<?php
//src/yourNS/UserBundle/Form/EventListener/AddRoleFieldSubscriber.php
namespace yourNS\UserBundle\Form\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AddRoleFieldSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(FormEvents::POST_SUBMIT => 'setRole');
}
public function setRole(FormEvent $event)
{
$aRoles = array('ROLE_USER');
/** @var $user \FOS\UserBundle\Model\UserInterface */
$user = $event->getForm()->getData();
$user->setRoles($aRoles);
}
}
Upvotes: 2
Reputation: 193
public function __construct()
{
parent::__construct();
$this->setRoles(["ROLE_WHATEVER"]);
}
Upvotes: 0
Reputation: 850
What i have done is override the entity constructor:
Here a piece of my Entity/User.php
public function __construct()
{
parent::__construct();
// your own logic
$this->roles = array('ROLE_USER');
}
This is the lazy way. If you want the right and better way see the @RayOnAir answer
Upvotes: 38
Reputation: 409
I think @RayOnAir solution is right way of doing this. But it will not work due to FOS default role handling
to make possible to persist default role in database one need to override User::setRoles() method (add it to your User entity):
/**
* Overriding Fos User class due to impossible to set default role ROLE_USER
* @see User at line 138
* @link https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Model/User.php#L138
* {@inheritdoc}
*/
public function addRole($role)
{
$role = strtoupper($role);
if (!in_array($role, $this->roles, true)) {
$this->roles[] = $role;
}
return $this;
}
Tested under:
Symfony version 2.3.6, FOSUserBundle 2.0.x-dev
Upvotes: 4
Reputation: 2048
The recommended way to do it as indicated by a main contributor to the FOSUserBundle (in the comment here linked) is to register an Event Listener on the REGISTRATION_SUCCESS event and use the $event->getForm()->getData()
to access the user and modify it.
Following those guidelines, I created the following listener (which works!):
<?php
// src/Acme/DemoBundle/EventListener/RegistrationListener.php
namespace Acme\DemoBundle\EventListener;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Listener responsible for adding the default user role at registration
*/
class RegistrationListener implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
FOSUserEvents::REGISTRATION_SUCCESS => 'onRegistrationSuccess',
);
}
public function onRegistrationSuccess(FormEvent $event)
{
$rolesArr = array('ROLE_USER');
/** @var $user \FOS\UserBundle\Model\UserInterface */
$user = $event->getForm()->getData();
$user->setRoles($rolesArr);
}
}
Also, the service needs to be registered as follows:
// src/Acme/DemoBundle/Resources/config/services.yml
services:
demo_user.registration_listener:
class: Acme\DemoBundle\EventListener\RegistrationListener
arguments: []
tags:
- { name: kernel.event_subscriber }
Notice that adding a default role in the User class __construct() may have some issues as indicated in this other answer.
Upvotes: 39
Reputation: 681
Ok now it's working with that :
public function onAddDefaultRoleSuccess(FilterUserResponseEvent $event)
{
$doctrine = $this->container->get('doctrine');
$em = $doctrine->getManager();
$user = $event->getUser();
$user->addRole('ROLE_BLOGGER');
$em->persist($user);
$em->flush();
}
I change my listener and know use REGISTRATION_COMPLETED. If someone has a better idea to do that, don't hesitate :)
Upvotes: 1