web-dev-qa-db-ja.com

FOSUserBundleでのユーザー登録時にデフォルトの役割を追加します

バージョン:Symfony 2.2

ユーザーが私のWebサイトに登録するときにデフォルトのロールを追加しようとしています。 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でリッスンする単純なイベントを作成しますが、何も機能しないようです。イベントとサービスを試すのは初めてです。だから誰かにアドバイスがあれば、私はそれを取る:)

ありがとう

26
Epok

私がやったことは、エンティティコンストラクタをオーバーライドすることです:

ここに私のEntity/User.phpの一部

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

これは怠zyな方法です。正しいより良い方法が必要な場合は、@ RayOnAirを参照してください answer

37
alvaropgl

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 に示されているようにいくつかの問題が発生する可能性があることに注意してください。

39
RayOnAir

@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

4
andrew

イベントサブスクライバーをフォームクラスに追加し、フォームイベント "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);
    }
}
2

OK、それで動作しています:

 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を知っています。誰かがそれを行うためのより良いアイデアを持っている場合、:しないでください:)

1
Epok
public function __construct()
{
    parent::__construct();
    $this->setRoles(["ROLE_WHATEVER"]);
}
0
jelle woord