以奏鸣曲管理员的编辑形式为用户设置角色
Posted
技术标签:
【中文标题】以奏鸣曲管理员的编辑形式为用户设置角色【英文标题】:set role for users in edit form of sonata admin 【发布时间】:2013-02-09 15:05:45 【问题描述】:我在一个项目中使用 Symfony 2.1。我使用 FOSUserBundle 管理用户,使用 SonataAdminBundle 进行管理。
我对此有一些疑问:
作为管理员,我想在用户编辑表单中设置用户角色。如何访问role_hierarchy
中的角色?以及如何将它们用作选择字段,以便管理员可以为用户设置角色?
当我在列表中显示角色时,它显示为这样的字符串:
[0 => ROLE_SUPER_ADMIN] [1 => ROLE_USER]
我怎样才能把它改成这个?
ROLE_SUPER_ADMIN, ROLE_USER
我的意思是,只有数组的值。
【问题讨论】:
【参考方案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')
希望这能解决您的问题
【讨论】:
以上是关于以奏鸣曲管理员的编辑形式为用户设置角色的主要内容,如果未能解决你的问题,请参考以下文章