简体   繁体   English

在sonata admin的编辑形式中为用户设置角色

[英]set role for users in edit form of sonata admin

I'm using Symfony 2.1 for a project. 我正在使用Symfony 2.1进行项目。 I use the FOSUserBundle for managing users & SonataAdminBundle for administration usage. 我使用FOSUserBundle管理用户和SonataAdminBundle管理用法。

I have some questions about that: 我有一些问题:

  1. As an admin, I want to set roles from users in users edit form. 作为管理员,我想在用户编辑表单中设置用户角色。 How can I have access to roles in role_hierarchy ? 如何访问role_hierarchy角色? And how can I use them as choice fields so the admin can set roles to users? 我如何将它们用作选择字段,以便管理员可以为用户设置角色?

  2. When I show roles in a list, it is shown as string like this: 当我在列表中显示角色时,它显示为如下字符串:

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

    How can I change it to this? 我该如何改变它呢?

     ROLE_SUPER_ADMIN, ROLE_USER 

    I mean, having just the value of the array. 我的意思是,只有数组的值。

Based on the answer of @parisssss although it was wrong, here is a working solution. 根据@parisssss的答案虽然这是错误的,但这是一个有效的解决方案。 The Sonata input field will show all the roles that are under the given role if you save one role. 如果您保存一个角色,Sonata输入字段将显示给定角色下的所有角色。

On the other hand, in the database will be stored only the most important role. 另一方面,在数据库中将只存储最重要的角色。 But that makes absolute sense in the Sf way. 但这在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
        )
    );

And in another method: 而在另一种方法:

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

See it in action: 看到它的实际效果:

在此输入图像描述在此输入图像描述

As for the second question I added a method in the User class that looks like this 至于第二个问题,我在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);
 }

And then you can declare in your configureListFields function: 然后你可以在configureListFields函数中声明:

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

i found an answer for my first question!(but the second one in not answered yet..) i add the roles like below in configureFormFields function : 我找到了第一个问题的答案!(但第二个问题尚未解答..)我在configureFormFields函数中添加如下角色:

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

I would be very happy if anyone answers the second question :) 如果有人回答第二个问题我会很高兴:)

Romain Bruckert's solution is almost perfect, except that it doesn't allow to set roles, which are roots of role hierrarchy. Romain Bruckert的解决方案几乎是完美的,除了它不允许设置角色,这是角色层次结构的根源。 For instance ROLE_SUPER_ADMIN. 例如ROLE_SUPER_ADMIN。 Here's the fixed method flattenRoles, which also returns root roles: 这是固定方法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;
}

Edit: TrtG already posted this fix in comments 编辑:TrtG已在评论中发布此修复程序

Just to overplay it a bit, here is my enhanced version of Romain Bruckert and Sash which gives you an array like this: 只是为了夸大它,这是我的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))"
]

在此输入图像描述

This helps you find all roles , that include a specific role: 这有助于您找到包含特定角色的所有角色 在此输入图像描述

I know its much code, it could be done much better, but maybe it helps somebody or you can at least use pieces of this code. 我知道它的代码很多,它可以做得更好,但也许它可以帮助某人或者你至少可以使用这段代码。

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

The second answer is below. 第二个答案如下。 Add lines in sonata admin yml file . 在sonata admin yml文件中添加行。

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

and in user_roles.html.twig files add below lines 并在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 %}

then into your admin controller and in configureListFields function add this line 然后进入你的管理控制器并在configureListFields函数中添加这一行

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

hope this will solve your problem 希望这能解决你的问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM