Module.php中的ZF3依赖项注入
我目前正在将ZF2应用程序迁移到ZF3。 大多数情况下,一切都很顺利,但有一件事我被卡住了 在我的Module.php中,我有一个使用zend权限ACL的ACL管理Module.php中的ZF3依赖项注入,php,zend-framework3,Php,Zend Framework3,我目前正在将ZF2应用程序迁移到ZF3。 大多数情况下,一切都很顺利,但有一件事我被卡住了 在我的Module.php中,我有一个使用zend权限ACL的ACL管理 class Module { protected $defaultLang = 'fr'; public function onBootstrap(MvcEvent $e) { $eventManager = $e->getApplication()->getEventManager();
class Module
{
protected $defaultLang = 'fr';
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
if (!$e->getRequest() instanceof ConsoleRequest){
$eventManager->attach(MvcEvent::EVENT_RENDER_ERROR, array($this, 'onRenderError'));
$eventManager->attach(MvcEvent::EVENT_RENDER, array($this, 'onRender'));
$eventManager->attach(MvcEvent::EVENT_FINISH, array($this, 'onFinish'));
$this->initAcl($e);
$eventManager->attach('route', array($this, 'checkAcl'));
}
}
public function checkAcl(MvcEvent $e) {
$app = $e->getApplication();
$sm = $app->getServiceManager();
$route = $e -> getRouteMatch() -> getMatchedRouteName();
$authService = $sm->get('AuthenticationService');
$jwtService = $sm->get('JwtService');
$translator = $sm->get('translator');
$identity = null;
try {
$identity = $jwtService->getIdentity($e->getRequest());
} catch(\Firebase\JWT\ExpiredException $exception) {
$response = $e->getResponse();
$response->setStatusCode(401);
return $response;
}
if(is_null($identity) && $authService->hasIdentity()) { // no header being passed on... we try to use standard validation
$authService->setJwtMode(false);
$identity = $authService->getIdentity();
}
$userRole = 'default';
$translator->setLocale($this->defaultLang);
if(!is_null($identity))
{
$userRole = $identity->getType();
//check if client or prospect
if($userRole >= User::TYPE_CLIENT)
{
$userManagementRight = UserRight::CREATE_USERS;
if($identity->hasRight($userManagementRight))
$userRole = 'userManagement';
}
$translator->setLocale($identity->getLang());
}
if (!$e->getViewModel()->acl->isAllowed($userRole, null, $route)) {
$response = $e -> getResponse();
$response->setStatusCode(403);
return $response;
}
public function initAcl(MvcEvent $e) {
//here is list of routes allowed
}
}
我这里的问题是,我仍然在使用getServiceManager,因此收到了不推荐使用的警告:自v3.0.0以来,Zend\ServiceManager\ServiceManager::getServiceLocator的用法已不推荐使用代码>
基本上,我只需要将依赖项注入Module.php。
我猜,否则我将不得不直接将checkAcl移动到控制器,并将ACL注入其中?不确定这样做的正确方式是什么
对此的任何反馈都将不胜感激
问候,
Robert要解决此问题,应使用侦听器类和工厂。它还可以帮助您更好地分离关注点:)
从你的代码来看,你似乎很有能力把事情弄清楚。因此,我只想给你一个我自己的例子,所以你应该用你自己的代码来填充你的代码(我也有点懒,当我可以复制/粘贴我的代码时,我不想重写所有的东西;)
在module.config.php
中:
'listeners' => [
// Listing class here will automatically have them "activated" as listeners
ActiveSessionListener::class,
],
'service_manager' => [
'factories' => [
// The class (might need a) Factory
ActiveSessionListener::class => ActiveSessionListenerFactory::class,
],
],
工厂
<?php
namespace User\Factory\Listener;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\EntityManager;
use Interop\Container\ContainerInterface;
use User\Listener\ActiveSessionListener;
use Zend\Authentication\AuthenticationService;
use Zend\ServiceManager\Factory\FactoryInterface;
class ActiveSessionListenerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
/** @var ObjectManager $entityManager */
$entityManager = $container->get(EntityManager::class);
/** @var AuthenticationService $authenticationService */
$authenticationService = $container->get(AuthenticationService::class);
return new ActiveSessionListener($authenticationService, $entityManager);
}
}
要解决这个问题,您应该使用侦听器类和工厂。它还可以帮助您更好地分离关注点:)
从你的代码来看,你似乎很有能力把事情弄清楚。因此,我只想给你一个我自己的例子,所以你应该用你自己的代码来填充你的代码(我也有点懒,当我可以复制/粘贴我的代码时,我不想重写所有的东西;)
在module.config.php
中:
'listeners' => [
// Listing class here will automatically have them "activated" as listeners
ActiveSessionListener::class,
],
'service_manager' => [
'factories' => [
// The class (might need a) Factory
ActiveSessionListener::class => ActiveSessionListenerFactory::class,
],
],
工厂
<?php
namespace User\Factory\Listener;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\EntityManager;
use Interop\Container\ContainerInterface;
use User\Listener\ActiveSessionListener;
use Zend\Authentication\AuthenticationService;
use Zend\ServiceManager\Factory\FactoryInterface;
class ActiveSessionListenerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
/** @var ObjectManager $entityManager */
$entityManager = $container->get(EntityManager::class);
/** @var AuthenticationService $authenticationService */
$authenticationService = $container->get(AuthenticationService::class);
return new ActiveSessionListener($authenticationService, $entityManager);
}
}
非常感谢,这是一个令人惊讶的回答。我明天会测试它,但我相信它正是我所需要的!:-)再次感谢你,它工作得很好。我唯一的问题是优先级设置为1000,这使得我的事件在没有路由匹配的情况下发生。把它设回默认值1,其他一切都会顺利进行。是的,这正是你可能给自己的优先权。对我来说,它是一个ActiveSessionListener
。在早期,我想知道谁在使用我的应用程序,所以它会以这个优先级提前触发。在999优先级时,我获得了一个授权侦听器,以确保在1000优先级时确定的用户被检查为允许在路由上;-)非常感谢,这是一个令人惊讶的回答。我明天会测试它,但我相信它正是我所需要的!:-)再次感谢你,它工作得很好。我唯一的问题是优先级设置为1000,这使得我的事件在没有路由匹配的情况下发生。把它设回默认值1,其他一切都会顺利进行。是的,这正是你可能给自己的优先权。对我来说,它是一个ActiveSessionListener
。在早期,我想知道谁在使用我的应用程序,所以它会以这个优先级提前触发。在999优先级时,我获得了一个授权侦听器,以确保在1000优先级时确定的用户被检查为允许在路由上;-)