0

我有一个查找用户授权的插件。

我在我的 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);


....

当然找不到插件,它还没有加载:

调用未定义的方法 User\Module::access()

无论如何,我想调用插件方法。在这种情况下有可能使用它吗?像这样的东西:

        $grantplugin = fetch/call the plugin
        $isgranted = $grantplugin->checkAccess($controllerName, $actionName);

任何帮助表示赞赏!

**编辑:我尝试了 ermengildo 给我的解决方案。但它不起作用,原因是我还没有和工厂合作过。在一些帮助下,我可能可以学会如何正确地做到这一点。这是我的乳头:

我在这里找到了两个服务:

服务地点

我将 module.php 更改为(片段!):

公共函数 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,
    ],
],

备注:这里已经有语法警告:...无法解析为类型

如果我调试,我会得到一个异常:

无法将服务“User\Service\AccessControl”解析为工厂;你确定你在配置过程中提供了它吗?

在进一步的解释中,我的 module.php 中的这一行应该是问题所在:

 $accessService = $container->get(Service\AccessControl::class);
4

1 回答 1

1

问题不在于“尚未加载插件”,而是您不在控制器内,并且您正在尝试调用控制器插件。

您必须在这里创建一个服务,从服务管理器中检索一个实例,然后调用该实例上的方法。

例子

模块.config.php

'service_manager' => [
    'factories' => [
        // Avoid anonymous functions
        \User\Service\AccessControl::class => \User\Service\AccessControlFactory::class
    ]
]

访问控制工厂

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类中创建它并使用它:

用户\模块

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 所做的评论,因为这是进行访问控制的正确方法。;)

于 2019-10-14T13:33:33.750 回答