25

版本:Symfony 2.2

当用户在我的网站上注册时,我正在尝试添加默认角色。我使用 FOSUserBundle,我看到当用户注册时,角色字段在数据库中为空。我从这个巨大的捆绑包开始,它不是很容易理解。所以我阅读了所有文档,但我不知道该怎么做。

现在,我创建了一个事件来动态添加这个角色,但它不起作用(我没有错误,但我的数据库仍然是空的)我什至不知道这是做到这一点的好方法吗?

我的活动:

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);
  }
}

如您所见,我创建了一个简单的事件来监听 REGISTRATION_SUCCESS,但似乎没有任何效果。这是我第一次尝试使用事件和服务。所以如果有人有建议,我会接受的:)

4

6 回答 6

39

正如 FOSUserBundle 的主要贡献者(在此处链接的评论中)所指出的那样,推荐的方法是在 REGISTRATION_SUCCESS 事件上注册一个事件侦听器并使用$event->getForm()->getData()来访问用户并对其进行修改。遵循这些准则,我创建了以下监听器(有效!):

<?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);
    }
}

此外,服务需要注册如下:

// src/Acme/DemoBundle/Resources/config/services.yml
services:
    demo_user.registration_listener:
        class: Acme\DemoBundle\EventListener\RegistrationListener
        arguments: []
        tags:
            - { name: kernel.event_subscriber }

请注意,在 User 类 __construct() 中添加默认角色可能会出现一些问题,如this other answer所示。

于 2013-06-22T20:53:06.860 回答
37

我所做的是覆盖实体构造函数:

这是我的 Entity/User.php 的一部分

public function __construct()
{
    parent::__construct();
    // your own logic
    $this->roles = array('ROLE_USER');
}

这是偷懒的方式。如果您想要正确和更好的方法,请参阅@RayOnAir答案

于 2013-04-14T09:08:03.543 回答
4

我认为@RayOnAir 解决方案是这样做的正确方法。但由于FOS 默认角色处理,它不起作用

为了能够在数据库中保留默认角色,需要重写 User::setRoles() 方法(将其添加到您的 User 实体):

/**
 * 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;
}

测试下:

Symfony 2.3.6版,FOSUserBundle 2.0.x-dev

于 2013-10-31T10:02:00.663 回答
2

您可以将事件订阅者添加到表单类并使用表单事件“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';
    }
}

现在添加角色字段的逻辑位于它自己的订阅者类中

<?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);
    }
}
于 2015-08-14T01:31:40.663 回答
1

好的,现在它正在使用它:

 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();
}

我改变了我的听众并知道使用REGISTRATION_COMPLETED。如果有人有更好的主意,请不要犹豫:)

于 2013-04-13T23:25:48.527 回答
0
public function __construct()
{
    parent::__construct();
    $this->setRoles(["ROLE_WHATEVER"]);
}
于 2017-10-26T14:22:43.000 回答