Как использовать метод плагина в событии onDispatch? - PullRequest
0 голосов
/ 11 октября 2019

У меня есть плагин, который просматривает пользовательские разрешения.

Я объявил его в своем файле 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. Но это не работает, причина в том, что я еще не работал с фабриками. С небольшой помощью я, вероятно, смогу научиться делать это правильно. Вот мои ниппеты:

Я разместил здесь две службы:

location of services

Я изменил module.php на (фрагмент!):

публичная функция onDispatch (событие MvcEvent $) {

    $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,
    ],
],

Примечание: здесь уже естьпредупреждение о синтаксисе: ... не может быть преобразовано в тип

Если я отлаживаю, я получаю исключение:

Невозможно разрешить службу "Пользователь \ Сервис \ AccessControl" взавод;Вы уверены, что предоставили его во время настройки?

В дальнейшем объяснении этой строки в моем module.php должна быть проблема:

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

1 Ответ

1 голос
/ 14 октября 2019

Проблема не в том, что «плагин еще не загружен», а в том, что вы не находитесь внутри контроллера , и вы пытаетесь вызвать контроллер плагин.

Здесь необходимо создать службу, извлечь экземпляр из диспетчера служб и вызвать метод для этого экземпляра.

Пример

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);

    }

}

AccessControl

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, потому что это правильный способ управления доступом. ;)

...