在我的Symfony 2应用程序中,我有3个不同的用户角色,可以访问后端管理部分:
role_hierarchy:
ROLE_STAFF: ROLE_USER
ROLE_MODERATOR: ROLE_STAFF
ROLE_ADMIN: ROLE_MODERATOR
Run Code Online (Sandbox Code Playgroud)
对于像这样的路线http://example.org/admin/post/,我希望我的应用程序根据用户角色显示不同的信息,这意味着3个控制器绑定到唯一的路径.
处理这个问题的最佳方法是什么?
我在考虑一些解决方案,但似乎没有一个对我好:
一个控制器,在每个动作中我只测试用户角色:
<?php
/**
* @Route("/admin/post")
*/
class PostController extends Controller
{
/**
* Lists all post entities.
*
* @Route("/", name="post_index")
* @Template()
* @Secure(roles="ROLE_STAFF")
*/
public function indexAction()
{
$user = $this->get('security.context')->getToken()->getUser();
if ($this->get('security.context')->isGranted('ROLE_STAFF')) {
// Do ROLE_STAFF related stuff
} else if ($this->get('security.context')->isGranted('ROLE_MODERATOR')) {
// Do ROLE_MODERATOR related stuff
} else if ($this->get('security.context')->isGranted('ROLE_ADMIN')) {
// Do ROLE_ADMIN related stuff
}
return array('posts' => $posts);
}
}
Run Code Online (Sandbox Code Playgroud)
即使这样做,IMO显然不是一个好的设计.
一个BackendController调度到3个不同的控制器:
<?php
/**
* @Route("/admin/post")
*/
class PostBackendController extends Controller
{
/**
* Lists all post entities.
*
* @Route("", name="admin_post_index")
* @Template("AcmeBlogBundle:PostAdmin:index.html.twig")
* @Secure(roles="ROLE_STAFF")
*/
public function indexAction()
{
if ($this->get('security.context')->isGranted('ROLE_STAFF')) {
$response = $this->forward('AcmeBlogBundle:PostStaff:index');
} else if ($this->get('security.context')->isGranted('ROLE_MODERATOR')) {
$response = $this->forward('AcmeBlogBundle:PostModerator:index');
} else if ($this->get('security.context')->isGranted('ROLE_ADMIN')) {
$response = $this->forward('AcmeBlogBundle:PostAdmin:index');
}
return $response;
}
}
Run Code Online (Sandbox Code Playgroud)
与第一名相同.
我试图使控制器彼此扩展:
<?php
/**
* @Route("/admin/post")
*/
class PostStaffController extends Controller
{
/**
* Lists all post entities.
*
* @Route("/", name="post_index")
* @Template()
* @Secure(roles="ROLE_STAFF")
*/
public function indexAction()
{
$user = $this->get('security.context')->getToken()->getUser();
// Do ROLE_STAFF related stuff
return array('posts' => $posts);
}
}
<?php
/**
* @Route("/admin/post")
*/
class PostModeratorController extends PostStaffController
{
/**
* Lists all post entities.
*
* @Route("/", name="post_index")
* @Template()
* @Secure(roles="ROLE_MODERATOR")
*/
public function indexAction()
{
$user = $this->get('security.context')->getToken()->getUser();
// As PostModeratorController extends PostStaffController,
// I can either use parent action or redefine it here
return array('posts' => $posts);
}
}
<?php
/**
* @Route("/admin/post")
*/
class PostAdminController extends PostModeratorController
{
/**
* Lists all post entities.
*
* @Route("/", name="post_index")
* @Template()
* @Secure(roles="ROLE_ADMIN")
*/
public function indexAction()
{
$user = $this->get('security.context')->getToken()->getUser();
// Same applies here
return array('posts' => $posts);
}
}
Run Code Online (Sandbox Code Playgroud)
IMO它是一个更好的设计,但我无法使其成功.路由系统在匹配的第一个控制器上停止.我想让它自动成为级联风格的王者(即如果用户是工作人员则转到PostStaffController,否则如果用户是主持人转到PostModeratorController,否则转到PostAdminController).
在我的BlogBundle中为kernel.controller添加一个监听器,它将完成与2号相同的工作?
我正在寻找最好的设计和更灵活的解决方案,我们有可能在未来增加更多的角色.
您的第二个解决方案的自动化版本怎么样?喜欢:
// Roles ordered from most to least significant (ROLE_ADMIN -> ROLE_MODERATOR -> etc)
$roles = $myUserProvider->getRoles();
foreach ($roles as $role) {
// add a check to test, if the function you're calling really exists
$roleName = ucfirst(strtolower(mb_substr($role, 0, 5)));
$response = $this->forward(sprintf('AcmeBlogBundle:Post%s:index', $roleName))
break;
}
// Check that $response is not null and do something with it ...
Run Code Online (Sandbox Code Playgroud)
由于我没有你的设置,所以我没有测试上面的代码。顺便说一句:不同的发布方法有什么区别?
| 归档时间: |
|
| 查看次数: |
2915 次 |
| 最近记录: |