将角色列表添加到 FOS 用户包配置文件编辑表单

问题描述 投票:0回答:2

这个问题类似于 Symfony2:在 FormBuilder 中获取用户角色列表,但那里的答案适用于任何表单,但我的问题特定于由 User Bundle 创建的表单。问题是 UserBundle 控制器创建这样的表单:

$form = $this->container->get('fos_user.profile.form');

因此,我不知道如何将角色发送到我的表单类型。

php symfony fosuserbundle
2个回答
2
投票

我的答案与@Mihai Aurelian 在类似问题中的回答类似。

创建了一个名为 Role Helper 的服务:

<?php

namespace AppBundle\Services;

/**
 * Roles helper displays roles set in config.
 */
class RolesHelper
{
  private $rolesHierarchy;

  public function __construct($rolesHierarchy)
  {
    $this->rolesHierarchy = $rolesHierarchy;
  }

  /**
   * Return roles.
   *
   * @return array
   */
  public function getRoles()
  {
    $roles = array();

    array_walk_recursive($this->rolesHierarchy, function($val) use (&$roles) {
      $roles[] = $val;
    });

    return array_unique($roles);
  }
}

使用覆盖默认 FOSUserBundle Forms 指令覆盖表单类型,并更新默认构造函数以包含 RolesHelper 作为参数。

<?php

namespace AppBundle\Form\Type;

use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
use AppBundle\Services\RolesHelper;

class UserType extends BaseType
{
  /**
   * @var RolesHelper
   */
  private $roles;

  /**
   * @param string $class The User class name
   * @param RolesHelper $roles Array or roles.
   */
  public function __construct($class, RolesHelper $roles)
  {
    parent::__construct($class);

    $this->roles = $roles;
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(FormBuilderInterface $builder, array $options)
  {
    parent::buildForm($builder, $options);

    $builder->add('firstName')
            ->add('lastName')
            ->add('roles', 'choice', array(
              'choices' => $this->roles->getRoles(),
              'required' => false,
              'multiple'=>true
            ));
  }

  /**
   * {@inheritdoc}
   */
  public function getName()
  {
    return 'user_registration';
  }
}

更新了services.yml

app_roles_helper:
   class: AppBundle\Services\RolesHelper
   arguments: ['%security.role_hierarchy.roles%']

在 services.yml 中的 app_user.registration.form.type 添加了第二个参数:

app_user.registration.form.type:
  class: AppBundle\Form\Type\UserType
  arguments: [%fos_user.model.user.class%, @app_roles_helper]
  tags:
    - { name: form.type, alias: user_registration }

0
投票

我无法发表评论,所以我将发表评论作为答案。按照您编写 getRoles 函数的方式,它只会返回数组位置作为角色,例如,如果您有一个三位置数组,它将返回 0,1,2 作为选择,而不是角色名称。然后我在这一行尝试了不同的东西,而不是:

array_walk_recursive($this->rolesHierarchy, function($val) use (&$roles) {
  $roles[] = $val;
});

我放了

array_walk_recursive($this->rolesHierarchy, function($val) use (&$roles) {
  $roles[$val] = $val;
});

这解决了返回数字数组位置而不是角色名称的问题。但是对于这样的层次结构有一个问题:

role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN: [ ROLE_ADMIN, ROLE_TEST ]

它只会返回 ROLE_USER、ROLE_ADMIN 和 ROLE_TEST,但对于 Symfony 来说,ROLE_ADMIN 和 ROLE_SUPER_ADMIN 也是角色。问题在于 array_walk_recursive 不会将其值是数组的键传递给回调函数。因为 ROLE_ADMIN 是 ARRAY(1) => ([0] => (string)ROLE_USER) 并且 ROLE_SUPER_ADMIN 是 ARRAY(2) => ([0]=>(string)ROLE_ADMIN [1]=>(string)ROLE_TEST),两者都会被忽略。

解决方案是这样做:

public function getRoles() {
    $roles = array();

    foreach (array_keys($this->rolesHierarchy) as $key){
        $roles[$key] = $key;
        array_walk_recursive($this->rolesHierarchy[$key], function($val) use (&$roles){
            $roles[$val] = $val;
        });
    }

    return array_unique($roles);

数组键本身也被视为角色,这就是包含 $roles[$key] = $key 的原因。并且,递归到层次结构中包含的每个数组:

        array_walk_recursive($this->rolesHierarchy[$key], function($val) use (&$roles){
            $roles[$val] = $val;
        });
© www.soinside.com 2019 - 2024. All rights reserved.