我在理解Demeter定律在Symfony的DI系统的某些情况下应该如何应用时遇到了一些问题。
我有一些工厂需要访问应用程序中的当前登录用户。要做到这一点,我需要@security.token_storage将其作为构造函数参数注入。
但在我的工厂中,要访问用户,我需要执行以下操作:$tokenStorage->getToken((->getUser((,最糟糕的是,如果我想访问用户的某些属性,我需要更深入一层。
根据德米特定律,你将如何解决这个问题?
这是我的代码示例:
class SomeFactory
{
/**
* @var User
*/
private $currentUser;
/**
* @param TokenStorageInterface $tokenStorage
*/
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->currentUser = $this->setCurrentUser($tokenStorage);
}
/**
* @param TokenStorageInterface $tokenStorage
*/
protected function setCurrentUser(TokenStorageInterface $tokenStorage)
{
if ($tokenStorage->getToken()
&& $tokenStorage->getToken()->getUser()
&& in_array('ADMIN_ROLE', $tokenStorage->getToken()->getUser()->getRoles())
) {
$this->currentUser = $tokenStorage->getToken()->getUser();
}
}
}
我希望我是清楚的。
非常感谢:(
在DI工厂中,会话似乎尚未初始化,这使得当前用户令牌此时不可用。
我做了什么让它工作:
-
为
kernel.event
:注册一个新的事件侦听器services: before_request_listener: class: AppEventListenerMyRequestListener tags: - name: kernel.event_listener event: kernel.request method: onKernelRequest
-
在
MyRequestListener
中,我添加了我的服务作为依赖项(它调用工厂(,并提供了数据不完整的服务。我还需要Security
:public function __construct(SymfonyComponentSecurityCoreSecurity $security, MyService $service) { $this->security = $security; $this->service = $service; }
-
现在,在
MyRequestListener::onKernelRequest
中,我可以访问用户的数据并添加/更改服务的不完整属性。public function onKernelRequest(): void { if ($user = $this->security->getUser()) { $this->service->whatever = $user->whatever; } }
因为Symfony使用相同的MyService
实例,所以这些修改将在所有进一步的服务中可用。
但请记住,当不存在活动用户会话时(例如,因为没有用户登录,或在CLI上(,您的服务也需要处理不完整的数据。