I have a plugin which looks up the user grants.
I declarated it in my module.config.php as follows:
'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,
]
],
In my onDispatch(MvcEvent $event)
event I want to fetch the http routing parameters, look up the grant and, if successful, redirect to the correct route.
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);
....
Of course the plugin can't be find, it isn't loaded yet:
Call to undefined method User\Module::access()
I'd like to call the plugin method anyway. Is there a possibility to use it in this case? Something like this:
$grantplugin = fetch/call the plugin
$isgranted = $grantplugin->checkAccess($controllerName, $actionName);
Any help appreciated!
**EDIT: I tried the solution ermengildo gave me. But it doesn't work, the reason is, that I haven't worked with factories yet. With a bit of help I can probably learn how to do it properly. Here my nippets:
I located the two services here:
I changed the module.php to (snippet!):
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(Service\AccessControl::class);
$accessService->access()->checkAccess($controllerName, $actionName);
Last I tried to declarate the service as a factory:
'service_manager' => [
'factories' => [
// Avoid anonymous functions
Service\AccessControl::class => Service\AccessControlFactory::class,
],
],
Remark: Here already I have the syntax warning: ...cannot be resolved to a type
If I debug, I get an exception:
Unable to resolve service "User\Service\AccessControl" to a factory; are you certain you provided it during configuration?
In the further explanation this line in my module.php shall be the problem:
$accessService = $container->get(Service\AccessControl::class);
The problem isn't that "the plugin hasn't been loaded yet", but that you are not inside a controller, and you are trying to call a controller plugin.
What you must do here is to create a service, retrive an instance from the service manager, and call the method on that instance.
Example
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
}
}
And finally, you can create it in your Module
class and use it:
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);
}
From your snippets, it is quite obvious what you are trying to achieve. I'd suggest you to take a look at this question/answer, and at the comment done by rkeet, because that's the proper way to do access controls. ;)