Symfony2: Getting the list of user roles in FormBu

2019-01-17 12:00发布

I'm making a form for user creation, and I want to give one or several roles to a user when I create him.

How do I get the list of roles defined in security.yml?

Here's my form builder at the moment:

public function buildForm(FormBuilder $builder, array $options)
{
    parent::buildForm($builder, $options);

    // add your custom fields
    $user = new User();
    $builder->add('regionUser');
    $builder->add('roles' ,'choice' ,array('choices' => $user->getRolesNames(),
            'required'  => true,
    ));

}

and in User.php

public function getRolesNames(){
    return array(
        "ADMIN" => "Administrateur",
        "ANIMATOR" => "Animateur",
        "USER" => "Utilisateur",        
    );
}

Of course, this solution doesn't work, because roles is defined as a bitmap in the database, therefore the choices list cannot be created.

Thanks in advance.

10条回答
孤傲高冷的网名
2楼-- · 2019-01-17 12:18

security.role_hierarchy.roles container parameter holds the role hierarchy as an array. You can generalize it to get list of roles defined.

查看更多
别忘想泡老子
3楼-- · 2019-01-17 12:22

You can get a list of reachable roles from this method:

Symfony\Component\Security\Core\Role\RoleHierarchy::getReachableRoles(array $roles)

It seems to return all roles reachable from roles in array $roles parameter. It's an internal service of Symfony, whose ID is security.role_hierarchy and is not public (you must explicitely pass it as parameters, it's not acessible from Service Container).

查看更多
【Aperson】
4楼-- · 2019-01-17 12:22

In Symfony 2.7, in controllers you have to use $this->getParameters() to get roles :

$roles = array();
foreach ($this->getParameter('security.role_hierarchy.roles') as $key => $value) {
    $roles[] = $key;

    foreach ($value as $value2) {
        $roles[] = $value2;
    }
}
$roles = array_unique($roles);
查看更多
beautiful°
5楼-- · 2019-01-17 12:23

If you need to get all inherited roles of certain role:

use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\Role\RoleHierarchy;

private function getRoles($role)
{
    $hierarchy = $this->container->getParameter('security.role_hierarchy.roles');
    $roleHierarchy = new RoleHierarchy($hierarchy);
    $roles = $roleHierarchy->getReachableRoles([new Role($role)]);
    return array_map(function(Role $role) { return $role->getRole(); }, $roles);
}

Then call this functon: $this->getRoles('ROLE_ADMIN');

查看更多
迷人小祖宗
6楼-- · 2019-01-17 12:27

Here's what I've done:

FormType:

use FTW\GuildBundle\Entity\User;

class UserType extends AbstractType
{

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('username')
        ->add('email')
        ->add('enabled', null, array('required' => false))
        ->add('roles', 'choice', array(
        'choices' => User::getRoleNames(),
        'required' => false,'label'=>'Roles','multiple'=>true
    ))
        ->add('disableNotificationEmails', null, array('required' => false));
}

In the entity:

use Symfony\Component\Yaml\Parser; ...

static function getRoleNames()
{
    $pathToSecurity = __DIR__ . '/../../../..' . '/app/config/security.yml';
    $yaml = new Parser();
    $rolesArray = $yaml->parse(file_get_contents($pathToSecurity));
    $arrayKeys = array();
    foreach ($rolesArray['security']['role_hierarchy'] as $key => $value)
    {
        //never allow assigning super admin
        if ($key != 'ROLE_SUPER_ADMIN')
            $arrayKeys[$key] = User::convertRoleToLabel($key);
        //skip values that are arrays --- roles with multiple sub-roles
        if (!is_array($value))
            if ($value != 'ROLE_SUPER_ADMIN')
                $arrayKeys[$value] = User::convertRoleToLabel($value);
    }
    //sort for display purposes
    asort($arrayKeys);
    return $arrayKeys;
}

static private function convertRoleToLabel($role)
{
    $roleDisplay = str_replace('ROLE_', '', $role);
    $roleDisplay = str_replace('_', ' ', $roleDisplay);
    return ucwords(strtolower($roleDisplay));
}

Please do provide feedback... I've used some suggestions from other answers, but I still feel like this is not the best solution!

查看更多
唯我独甜
7楼-- · 2019-01-17 12:32

This is not exactly what you want but it makes your example working:

use Vendor\myBundle\Entity\User;

public function buildForm(FormBuilder $builder, array $options)
{
    parent::buildForm($builder, $options);

    // add your custom fields
    $user = new User();
    $builder->add('regionUser');
    $builder->add('roles' ,'choice' ,array('choices' => User::getRolesNames(),
            'required'  => true,
    ));
}

But regarding getting your Roles from an entity, maybe you can use entity repository stuff to query the database.

Here is a good example to get what to want using the queryBuilder into the entity repository:

public function buildForm(FormBuilder $builder, array $options)
{
    parent::buildForm($builder, $options);

    // add your custom fields
    $user = new User();
    $builder->add('regionUser');
    $builder->add('roles' ,'entity' array(
                 'class'=>'Vendor\MyBundle\Entity\User',
                 'property'=>'roles',
                 'query_builder' => function (\Vendor\MyBundle\Entity\UserRepository $repository)
                 {
                     return $repository->createQueryBuilder('s')
                            ->add('orderBy', 's.sort_order ASC');
                 }
                )
          );
}

http://inchoo.net/tools-frameworks/symfony2-entity-field-type/

查看更多
登录 后发表回答