我的用户拥有countTasks
属性,具有相应的setter和getter:
class User implements UserInterface, \Serializable
{
/**
* @var integer
*/
private $countTasks;
}
我希望此属性始终显示在应用程序的导航栏中(红色的“14”数字):
显然,应该为每个控制器设置此属性。 (实际上,只针对渲染导航栏的每一个,但这不是这种情况)。因此,应用程序应为每个控制器计算当前登录用户的任务。
我在Symfony食谱中找到了一个相关主题:How to Setup before and after Filters,我设法实现了它:
Acme\TestBundle\EventListener\UserListener.php
:
namespace Acme\TestBundle\EventListener;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
class UserListener
{
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
if ( ! is_array($controller)) {
return;
}
$securityContext = $controller[0]->get('security.context');
// now count tasks, but only if a user logged-in
if ($securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED') or $securityContext->isGranted('IS_AUTHENTICATED_FULLY'))
{
$user = $securityContext->getToken()->getUser();
// ...
// countig tasks and setting $countTasks var
// ...
$user->setCountTasks($countTasks);
}
}
}
services.yml
:
services:
acme.user.before_controller:
class: Acme\TestBundle\EventListener\UserListener
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
它按预期工作,我可以在Twig模板中拉出属性,如下所示:
{{ app.user.countTasks }}
它在prod env中的预期效果
然而,在开发人员中,探查器会抛出UndefinedMethodException
:
UndefinedMethodException:尝试在... \ src \ Acme \ TestBundle \ EventListener \ UserListener.php第18行的类“Symfony \ Bundle \ WebProfilerBundle \ Controller \ ProfilerController”上调用方法“get”。
第18行是这一行:
$securityContext = $controller[0]->get('security.context');
作为快速补丁,我添加了额外的检查(第18行之前),以防止探查器执行进一步的逻辑:
if (is_a($controller[0], '\Symfony\Bundle\WebProfilerBundle\Controller\ProfilerController'))
{
return;
}
$securityContext = $controller[0]->get('security.context');
它已经成功了。但我担心这不是正确的方法。我也担心我在分析器中丢失了部分调试信息。
我对我的担忧是对的吗?你能指点我一个更好的方法来阻止探查器执行这个监听器吗?在配置中某种程度?
答案 0 :(得分:2)
即使在Symfony的文档How to Setup before and after Filters中,第29行也是instanceof condition is being evaluated。
我会说,如果医生正在这样做,你自己做得很安全(除非另有说明,但事实并非如此)。
答案 1 :(得分:1)
一开始我试图反过来解决这个问题。在测试期间,我发现我必须排除其他一些核心控制器。当然,我应该只允许所需的控制器,而不是阻止不需要的控制器。
我最终创建了一个空接口UserTasksAwareController
:
namespace Acme\TestBundle\Controller;
interface UserTasksAwareController
{}
在UserListener.php
中确定有效性检查:
if ( ! $controllers[0] instanceof UserTasksAwareController) {
return;
}
并在处理显示countTasks
属性的每个其他控制器中实现它,如下所示:
class UserController extends Controller implements UserTasksAwareController
所以,当你忘记编程接口而不是实现时,我遇到的问题只是另一个问题。