【问题标题】:set role for users in edit form of sonata admin以奏鸣曲管理员的编辑形式为用户设置角色
【发布时间】:2013-02-09 15:05:45
【问题描述】:

我在一个项目中使用 Symfony 2.1。我使用 FOSUserBundle 管理用户,使用 SonataAdminBundle 进行管理。

我对此有一些疑问:

  1. 作为管理员,我想在用户编辑表单中设置用户角色。如何访问role_hierarchy 中的角色?以及如何将它们用作选择字段,以便管理员可以为用户设置角色?

  2. 当我在列表中显示角色时,它显示为这样的字符串:

    [0 => ROLE_SUPER_ADMIN] [1 => ROLE_USER] 
    

    我怎样才能把它改成这个?

    ROLE_SUPER_ADMIN, ROLE_USER 
    

    我的意思是,只有数组的值。

【问题讨论】:

    标签: symfony symfony-2.1 fosuserbundle sonata-admin user-roles


    【解决方案1】:

    根据@parisssss 的回答,虽然它是错误的,但这是一个可行的解决方案。如果您保存一个角色,则奏鸣曲输入字段将显示给定角色下的所有角色。

    另一方面,在数据库中只会存储最重要的角色。但这在 Sf 方式中是绝对有意义的。

    protected function configureFormFields(FormMapper $formMapper) {
    // ..
    $container = $this->getConfigurationPool()->getContainer();
    $roles = $container->getParameter('security.role_hierarchy.roles');
    
    $rolesChoices = self::flattenRoles($roles);
    
    $formMapper
        //...
        ->add('roles', 'choice', array(
               'choices'  => $rolesChoices,
               'multiple' => true
            )
        );
    

    另外一种方法:

    /**
     * Turns the role's array keys into string <ROLES_NAME> keys.
     * @todo Move to convenience or make it recursive ? ;-)
     */
    protected static function flattenRoles($rolesHierarchy) 
    {
        $flatRoles = array();
        foreach($rolesHierarchy as $roles) {
    
            if(empty($roles)) {
                continue;
            }
    
            foreach($roles as $role) {
                if(!isset($flatRoles[$role])) {
                    $flatRoles[$role] = $role;
                }
            }
        }
    
        return $flatRoles;
    }
    

    查看实际操作:

    【讨论】:

    • 该解决方案也适用于具有相同配置的configureListFields 方法
    • 酷,刚刚添加了 "foreach ($rolesHierarchy as $key => $roles) { $flatRoles[$key] = $key; (...)" 所以它不仅抓住了所有可用的角色孩子们。
    【解决方案2】:

    至于第二个问题,我在 User 类中添加了一个方法,看起来像这样

    /**
     * @return string
     */
     public function getRolesAsString()
     {
         $roles = array();
         foreach ($this->getRoles() as $role) {
            $role = explode('_', $role);
            array_shift($role);
            $roles[] = ucfirst(strtolower(implode(' ', $role)));
         }
    
         return implode(', ', $roles);
     }
    

    然后你可以在你的configureListFields 函数中声明:

    ->add('rolesAsString', 'string')
    

    【讨论】:

    • 感谢您的回答对我非常有用。我渲染角色时的列,现在称为rolesAsString,有什么方法可以重命名为“角色”吗?
    【解决方案3】:

    我找到了第一个问题的答案!(但第二个问题还没有回答..) 我在configureFormFields 函数中添加如下角色:

      protected function configureFormFields(FormMapper $formMapper) {
      //..
     $formMapper
     ->add('roles','choice',array('choices'=>$this->getConfigurationPool()->getContainer()->getParameter('security.role_hierarchy.roles'),'multiple'=>true ));
    }
    

    如果有人回答第二个问题,我会很高兴:)

    【讨论】:

    • 这导致值被存储为整数而不是字符串。我相信“角色”应该是一个字符串数组。
    • @JasonHanley 你是对的,当用户重新登录时它不起作用,他总是得到最不重要的角色。不应该接受答案。
    • 虽然我认为这是最有趣的答案。
    【解决方案4】:

    Romain Bruckert 的解决方案几乎是完美的,只是它不允许设置角色,这是角色层次结构的根源。例如 ROLE_SUPER_ADMIN。 这是固定方法 flattenRoles,它也返回根角色:

    protected static function flattenRoles($rolesHierarchy)
    {
        $flatRoles = [];
        foreach ($rolesHierarchy as $key => $roles) {
            $flatRoles[$key] = $key;
            if (empty($roles)) {
                continue;
            }
    
            foreach($roles as $role) {
                if(!isset($flatRoles[$role])) {
                    $flatRoles[$role] = $role;
                }
            }
        }
    
        return $flatRoles;
    }
    

    编辑:TrtG 已经在 cmets 中发布了这个修复

    【讨论】:

      【解决方案5】:

      有点夸张,这是我的 Romain Bruckert 和 Sash 的增强版本,它为您提供了这样的数组:

      array:4 [▼
        "ROLE_USER" => "User"
        "ROLE_ALLOWED_TO_SWITCH" => "Allowed To Switch"
        "ROLE_ADMIN" => "Admin (User, Allowed To Switch)"
        "ROLE_SUPER_ADMIN" => "Super Admin (Admin (User, Allowed To Switch))"
      ]
      

      这可以帮助您找到所有角色,其中包含特定角色:

      我知道它有很多代码,它可以做得更好,但也许它可以帮助某人,或者你至少可以使用这段代码。

      /**
       * Turns the role's array keys into string <ROLES_NAME> keys.
       * @param array $rolesHierarchy
       * @param bool $niceName
       * @param bool $withChildren
       * @param bool $withGrandChildren
       * @return array
       */
      protected static function flattenRoles($rolesHierarchy, $niceName = false, $withChildren = false, $withGrandChildren = false)
      {
          $flatRoles = [];
          foreach ($rolesHierarchy as $key => $roles) {
              if(!empty($roles)) {
                  foreach($roles as $role) {
                      if(!isset($flatRoles[$role])) {
                          $flatRoles[$role] = $niceName ? self::niceRoleName($role) : $role;
                      }
                  }
              }
              $flatRoles[$key] = $niceName ? self::niceRoleName($key) : $key;
              if ($withChildren && !empty($roles)) {
                  if (!$recursive) {
                      if ($niceName) {
                          array_walk($roles, function(&$item) { $item = self::niceRoleName($item);});
                      }
                      $flatRoles[$key] .= ' (' . join(', ', $roles) . ')';
                  } else {
                      $childRoles = [];
                      foreach($roles as $role) {
                          $childRoles[$role] = $niceName ? self::niceRoleName($role) : $role;
                          if (!empty($rolesHierarchy[$role])) {
                              if ($niceName) {
                                  array_walk($rolesHierarchy[$role], function(&$item) { $item = self::niceRoleName($item);});
                              }
                              $childRoles[$role] .= ' (' . join(', ', $rolesHierarchy[$role]) . ')';
                          }
                      }
                      $flatRoles[$key] .= ' (' . join(', ', $childRoles) . ')';
                  }
              }
          }
          return $flatRoles;
      }
      
      /**
       * Remove underscors, ROLE_ prefix and uppercase words
       * @param string $role
       * @return string
       */
      protected static function niceRoleName($role) {
          return ucwords(strtolower(preg_replace(['/\AROLE_/', '/_/'], ['', ' '], $role)));
      }
      

      【讨论】:

        【解决方案6】:

        第二个答案如下。 在奏鸣曲管理 yml 文件中添加行。

        sonata_doctrine_orm_admin:
            templates:
                types:
                    list:
                        user_roles: AcmeDemoBundle:Default:user_roles.html.twig
        

        并在user_roles.html.twig 文件中添加以下行

        {% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
        
        {% block field %}
            {% for row in value %}
                {{row}}
                {% if not loop.last %}
                ,
                {% endif %}
            {% endfor %}
        {% endblock %}
        

        然后进入您的管理控制器并在configureListFields 函数中添加此行

        ->add('roles', 'user_roles')
        

        希望这能解决您的问题

        【讨论】:

          猜你喜欢
          • 2018-04-30
          • 1970-01-01
          • 2019-02-12
          • 2019-02-16
          • 2018-08-11
          • 1970-01-01
          • 2014-12-20
          • 2019-10-13
          • 2019-01-14
          相关资源
          最近更新 更多