Symfony2: Getting the list of user roles in FormBuilder

前端 未结 10 1392
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-08 15:55

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.y

相关标签:
10条回答
  • 2020-12-08 16:29

    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');

    0 讨论(0)
  • 2020-12-08 16:36

    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/

    0 讨论(0)
  • 2020-12-08 16:37

    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);
    
    0 讨论(0)
  • 2020-12-08 16:42

    In Symfony 3.3, you can create a RolesType.php as follows:

    <?php
    
    namespace AppBundle\Form\Type;
    
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
    use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
    
    /**
     * @author Echarbeto
     */
    class RolesType extends AbstractType {
    
      private $roles = [];
    
      public function __construct(RoleHierarchyInterface $rolehierarchy) {
        $roles = array();
        array_walk_recursive($rolehierarchy, function($val) use (&$roles) {
          $roles[$val] = $val;
        });
        ksort($roles);
        $this->roles = array_unique($roles);
      }
    
      public function configureOptions(OptionsResolver $resolver) {
        $resolver->setDefaults(array(
            'choices' => $this->roles,
            'attr' => array(
                'class' => 'form-control',
                'aria-hidden' => 'true',
                'ref' => 'input',
                'multiple' => '',
                'tabindex' => '-1'
            ),
            'required' => true,
            'multiple' => true,
            'empty_data' => null,
            'label_attr' => array(
                'class' => 'control-label'
            )
        ));
      }
    
      public function getParent() {
        return ChoiceType::class;
      }
    
    }
    

    Then add it to the form as follows:

    $builder->add('roles', RolesType::class,array(
              'label' => 'Roles'
          ));
    

    Important is that each role must also be contained, for example: ROLE_ADMIN: [ROLE_ADMIN, ROLE_USER]

    0 讨论(0)
  • 2020-12-08 16:47

    For a correct representation of your roles, you need recursion. Roles can extend other roles.

    I use for the example the folowing roles in security.yml:

    ROLE_SUPER_ADMIN: ROLE_ADMIN
    ROLE_ADMIN:       ROLE_USER
    ROLE_TEST:        ROLE_USER
    

    You can get this roles with:

    $originalRoles = $this->getParameter('security.role_hierarchy.roles');
    

    An example with recursion:

    private function getRoles($originalRoles)
    {
        $roles = array();
    
        /**
         * Get all unique roles
         */
        foreach ($originalRoles as $originalRole => $inheritedRoles) {
            foreach ($inheritedRoles as $inheritedRole) {
                $roles[$inheritedRole] = array();
            }
    
            $roles[$originalRole] = array();
        }
    
        /**
         * Get all inherited roles from the unique roles
         */
        foreach ($roles as $key => $role) {
            $roles[$key] = $this->getInheritedRoles($key, $originalRoles);
        }
    
        return $roles;
    }
    
    private function getInheritedRoles($role, $originalRoles, $roles = array())
    {
        /**
         * If the role is not in the originalRoles array,
         * the role inherit no other roles.
         */
        if (!array_key_exists($role, $originalRoles)) {
            return $roles;
        }
    
        /**
         * Add all inherited roles to the roles array
         */
        foreach ($originalRoles[$role] as $inheritedRole) {
            $roles[$inheritedRole] = $inheritedRole;
        }
    
        /**
         * Check for each inhered role for other inherited roles
         */
        foreach ($originalRoles[$role] as $inheritedRole) {
            return $this->getInheritedRoles($inheritedRole, $originalRoles, $roles);
        }
    }
    

    The output:

    array (
      'ROLE_USER' => array(),
      'ROLE_TEST' => array(
                            'ROLE_USER' => 'ROLE_USER',
      ),
      'ROLE_ADMIN' => array(
                            'ROLE_USER' => 'ROLE_USER',
      ),
      'ROLE_SUPER_ADMIN' => array(
                            'ROLE_ADMIN' => 'ROLE_ADMIN',
                            'ROLE_USER' => 'ROLE_USER',
      ),
    )
    
    0 讨论(0)
  • 2020-12-08 16:50

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

    0 讨论(0)
提交回复
热议问题