如何在 onDispatch 事件中使用插件方法?
How to use a plugin method in the onDispatch event?
我有一个查找用户授权的插件。
我在我的 module.config.php 中声明如下:
'controller_plugins' => [
'factories' => [
Controller\Plugin\AccessPlugin::class => function($container) {
return new Controller\Plugin\AccessPlugin(
$container->get(Model\UserTable::class),
$container->get(Model\GrantsTable::class),
$container->get(Model\Authentication::class)
);
},
],
'aliases' => [
'access' => Controller\Plugin\AccessPlugin::class,
]
],
在我的 onDispatch(MvcEvent $event)
事件中,我想获取 http 路由参数,查找授权,如果成功,则重定向到正确的路由。
public function onDispatch(MvcEvent $event)
{
$controller = $event->getTarget();
$controllerName = $event->getRouteMatch()->getParam('controller', null);
$actionName = $event->getRouteMatch()->getParam('action', null);
$actionName = str_replace('-', '', lcfirst(ucwords($actionName, '-')));
$this->access()->checkAccess($controllerName, $actionName);
....
当然找不到插件,还没有加载:
Call to undefined method User\Module::access()
无论如何我都想调用插件方法。在这种情况下是否有可能使用它?像这样:
$grantplugin = fetch/call the plugin
$isgranted = $grantplugin->checkAccess($controllerName, $actionName);
感谢任何帮助!
**编辑:
我尝试了 ermengildo 给我的解决方案。但它不起作用,原因是,我还没有与工厂合作过。在一些帮助下,我可能可以学习如何正确地做到这一点。这是我的 nippets:
我在这里找到了两个服务:
我将 module.php 更改为(片段!):
public 函数 onDispatch(MvcEvent $event)
{
$controller = $event->getTarget();
$controllerName = $event->getRouteMatch()->getParam('controller', null);
$actionName = $event->getRouteMatch()->getParam('action', null);
$actionName = str_replace('-', '', lcfirst(ucwords($actionName, '-')));
$container = $event->getApplication()->getServiceManager();
$accessService = $container->get(Service\AccessControl::class);
$accessService->access()->checkAccess($controllerName, $actionName);
最后我尝试将服务声明为工厂:
'service_manager' => [
'factories' => [
// Avoid anonymous functions
Service\AccessControl::class => Service\AccessControlFactory::class,
],
],
备注:这里已经有语法警告了:
...无法解析为类型
如果我调试,我得到一个异常:
Unable to resolve service "User\Service\AccessControl" to a
factory; are you certain you provided it during configuration?
进一步解释我的module.php中的这一行应该是问题:
$accessService = $container->get(Service\AccessControl::class);
问题不在于 "the plugin hasn't been loaded yet",而是您不在 控制器 内,而您正试图调用 控制器 插件.
你必须在这里做的是创建一个服务,从服务管理器中检索一个实例,并在该实例上调用该方法。
例子
module.config.php
'service_manager' => [
'factories' => [
// Avoid anonymous functions
\User\Service\AccessControl::class => \User\Service\AccessControlFactory::class
]
]
AccessControlFactory
namespace User\Service;
use Zend\ServiceManager\Factory\FactoryInterface;
use User\Service\AccessControl;
class AccessControlFactory implements FactoryInterface {
/**
* Factory called
*
* @param \Interop\Container\ContainerInterface $container
* @param string $requestedName
* @param array|null $options
* @return TranslatorPlugin
*/
public function __invoke(\Interop\Container\ContainerInterface $container, $requestedName, array $options = null) {
$userTable = $container->get(\User\Model\UserTable::class);
$grantsTable = $container->get(\User\Model\GrantsTable::class);
$authentication = $container->get(\User\Model\Authentication::class);
return new AccessControl($userTable, $grantsTable, $authentication);
}
}
访问控制
namespace User\Service;
use User\Model\UserTable;
use User\Model\GrantsTable;
use User\Model\Authentication;
class AccessControl {
private $userTable;
private $grantsTable;
private $authentication;
function __construct(UserTable $userTable, GrantsTable $grantsTable, Authentication $authentication) {
$this->userTable = $userTable;
$this->grantsTable = $grantsTable;
$this->authentication = $authentication;
}
public function access(){
// Do your stuff
}
}
最后,您可以在 Module
class 中创建并使用它:
User\Module
public function onDispatch(MvcEvent $event) {
$controller = $event->getTarget();
$controllerName = $event->getRouteMatch()->getParam('controller', null);
$actionName = $event->getRouteMatch()->getParam('action', null);
$actionName = str_replace('-', '', lcfirst(ucwords($actionName, '-')));
$container = $event->getApplication()->getServiceManager();
$accessService = $container->get(\User\Service\AccessControl::class);
$accessService->access()->checkAccess($controllerName, $actionName);
}
旁注
从您的代码片段中可以很明显地看出您想要实现的目标。我建议您看一下 和 rkeet 所做的评论,因为这是进行访问控制的正确方法。 ;)
我有一个查找用户授权的插件。
我在我的 module.config.php 中声明如下:
'controller_plugins' => [
'factories' => [
Controller\Plugin\AccessPlugin::class => function($container) {
return new Controller\Plugin\AccessPlugin(
$container->get(Model\UserTable::class),
$container->get(Model\GrantsTable::class),
$container->get(Model\Authentication::class)
);
},
],
'aliases' => [
'access' => Controller\Plugin\AccessPlugin::class,
]
],
在我的 onDispatch(MvcEvent $event)
事件中,我想获取 http 路由参数,查找授权,如果成功,则重定向到正确的路由。
public function onDispatch(MvcEvent $event)
{
$controller = $event->getTarget();
$controllerName = $event->getRouteMatch()->getParam('controller', null);
$actionName = $event->getRouteMatch()->getParam('action', null);
$actionName = str_replace('-', '', lcfirst(ucwords($actionName, '-')));
$this->access()->checkAccess($controllerName, $actionName);
....
当然找不到插件,还没有加载:
Call to undefined method User\Module::access()
无论如何我都想调用插件方法。在这种情况下是否有可能使用它?像这样:
$grantplugin = fetch/call the plugin
$isgranted = $grantplugin->checkAccess($controllerName, $actionName);
感谢任何帮助!
**编辑: 我尝试了 ermengildo 给我的解决方案。但它不起作用,原因是,我还没有与工厂合作过。在一些帮助下,我可能可以学习如何正确地做到这一点。这是我的 nippets:
我在这里找到了两个服务:
我将 module.php 更改为(片段!):
public 函数 onDispatch(MvcEvent $event) {
$controller = $event->getTarget();
$controllerName = $event->getRouteMatch()->getParam('controller', null);
$actionName = $event->getRouteMatch()->getParam('action', null);
$actionName = str_replace('-', '', lcfirst(ucwords($actionName, '-')));
$container = $event->getApplication()->getServiceManager();
$accessService = $container->get(Service\AccessControl::class);
$accessService->access()->checkAccess($controllerName, $actionName);
最后我尝试将服务声明为工厂:
'service_manager' => [
'factories' => [
// Avoid anonymous functions
Service\AccessControl::class => Service\AccessControlFactory::class,
],
],
备注:这里已经有语法警告了: ...无法解析为类型
如果我调试,我得到一个异常:
Unable to resolve service "User\Service\AccessControl" to a factory; are you certain you provided it during configuration?
进一步解释我的module.php中的这一行应该是问题:
$accessService = $container->get(Service\AccessControl::class);
问题不在于 "the plugin hasn't been loaded yet",而是您不在 控制器 内,而您正试图调用 控制器 插件.
你必须在这里做的是创建一个服务,从服务管理器中检索一个实例,并在该实例上调用该方法。
例子
module.config.php
'service_manager' => [
'factories' => [
// Avoid anonymous functions
\User\Service\AccessControl::class => \User\Service\AccessControlFactory::class
]
]
AccessControlFactory
namespace User\Service;
use Zend\ServiceManager\Factory\FactoryInterface;
use User\Service\AccessControl;
class AccessControlFactory implements FactoryInterface {
/**
* Factory called
*
* @param \Interop\Container\ContainerInterface $container
* @param string $requestedName
* @param array|null $options
* @return TranslatorPlugin
*/
public function __invoke(\Interop\Container\ContainerInterface $container, $requestedName, array $options = null) {
$userTable = $container->get(\User\Model\UserTable::class);
$grantsTable = $container->get(\User\Model\GrantsTable::class);
$authentication = $container->get(\User\Model\Authentication::class);
return new AccessControl($userTable, $grantsTable, $authentication);
}
}
访问控制
namespace User\Service;
use User\Model\UserTable;
use User\Model\GrantsTable;
use User\Model\Authentication;
class AccessControl {
private $userTable;
private $grantsTable;
private $authentication;
function __construct(UserTable $userTable, GrantsTable $grantsTable, Authentication $authentication) {
$this->userTable = $userTable;
$this->grantsTable = $grantsTable;
$this->authentication = $authentication;
}
public function access(){
// Do your stuff
}
}
最后,您可以在 Module
class 中创建并使用它:
User\Module
public function onDispatch(MvcEvent $event) {
$controller = $event->getTarget();
$controllerName = $event->getRouteMatch()->getParam('controller', null);
$actionName = $event->getRouteMatch()->getParam('action', null);
$actionName = str_replace('-', '', lcfirst(ucwords($actionName, '-')));
$container = $event->getApplication()->getServiceManager();
$accessService = $container->get(\User\Service\AccessControl::class);
$accessService->access()->checkAccess($controllerName, $actionName);
}
旁注
从您的代码片段中可以很明显地看出您想要实现的目标。我建议您看一下