php Symfony2:获取 FormBuilder 中的用户角色列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11246774/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Symfony2: Getting the list of user roles in FormBuilder
提问by Gabriel Theron
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?
如何获取 中定义的角色列表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
并在 User.php
public function getRolesNames(){
return array(
"ADMIN" => "Administrateur",
"ANIMATOR" => "Animateur",
"USER" => "Utilisateur",
);
}
Of course, this solution doesn't work, because rolesis defined as a bitmap in the database, therefore the choiceslist cannot be created.
当然,这个方案是行不通的,因为roles在数据库中定义为位图,所以choices无法创建列表。
Thanks in advance.
提前致谢。
回答by Mun Mun Das
security.role_hierarchy.rolescontainer parameter holds the role hierarchy as an array. You can generalize it to get list of roles defined.
security.role_hierarchy.roles容器参数将角色层次结构保存为数组。您可以对其进行概括以获取定义的角色列表。
回答by AlterPHP
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 $rolesparameter. It's an internal service of Symfony, whose ID is security.role_hierarchyand is not public (you must explicitely pass it as parameters, it's not acessible from Service Container).
它似乎返回了可从数组$roles参数中的角色访问的所有角色。它是 Symfony 的内部服务,其 ID 是security.role_hierarchy公开的,也不是公开的(您必须明确地将其作为参数传递,它不能从服务容器中访问)。
回答by Mihai Aurelian
You can make a service for this and inject the "security.role_hierarchy.roles" parameter.
您可以为此创建一个服务并注入“security.role_hierarchy.roles”参数。
Service definition:
服务定义:
acme.user.roles:
class: Acme\DemoBundle\Model\RolesHelper
arguments: ['%security.role_hierarchy.roles%']
Service Class:
服务等级:
class RolesHelper
{
private $rolesHierarchy;
private $roles;
public function __construct($rolesHierarchy)
{
$this->rolesHierarchy = $rolesHierarchy;
}
public function getRoles()
{
if($this->roles) {
return $this->roles;
}
$roles = array();
array_walk_recursive($this->rolesHierarchy, function($val) use (&$roles) {
$roles[] = $val;
});
return $this->roles = array_unique($roles);
}
}
You can get the roles in your controller like this:
您可以像这样在控制器中获取角色:
$roles = $this->get('acme.user.roles')->getRoles();
回答by Tim Hovius
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:
我使用 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',
),
)
回答by Echarbeto
In Symfony 3.3, you can create a RolesType.php as follows:
在 Symfony 3.3 中,你可以创建一个 RolesType.php 如下:
<?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]
重要的是还必须包含每个角色,例如:ROLE_ADMIN: [ROLE_ADMIN, ROLE_USER]
回答by Alexey Pavlov
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');
然后调用这个函数: $this->getRoles('ROLE_ADMIN');
回答by Jonathan Delorme
In Symfony 2.7, in controllers you have to use $this->getParameters() to get roles :
在 Symfony 2.7 中,在控制器中你必须使用 $this->getParameters() 来获取角色:
$roles = array();
foreach ($this->getParameter('security.role_hierarchy.roles') as $key => $value) {
$roles[] = $key;
foreach ($value as $value2) {
$roles[] = $value2;
}
}
$roles = array_unique($roles);
回答by Chopchop
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 queryBuilderinto the entity repository:
这是使用queryBuilder将所需内容放入实体存储库的一个很好的示例:
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/
http://inchoo.net/tools-frameworks/symfony2-entity-field-type/
回答by Chris
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!
请提供反馈......我使用了其他答案中的一些建议,但我仍然觉得这不是最好的解决方案!
回答by Chopchop
//FormType
use Symfony\Component\Yaml\Parser;
function getRolesNames(){
$pathToSecurity = /var/mydirectory/app/config/security.yml
$yaml = new Parser();
$rolesArray = $yaml->parse(file_get_contents($pathToSecurity ));
return $rolesArray['security']['role_hierarchy']['ROLE_USER'];
}
This is so far the best way i found to get or set what i want from config files.
到目前为止,这是我发现从配置文件中获取或设置我想要的内容的最佳方式。
Bon courage
勇气可嘉

