Subhasis Laha
Subhasis Laha

Reputation: 101

Can't initialize my plugin function in ZF2 constructor

I am quite new to ZF2 and I am preparing a demo application with simple login and CRUD system. Now for login I have prepared a plugin which consists of some functions that will authenticate users, return the logged in user data, return the logged in status etc. But the problem that I am facing is I can't initialize any variable into the constructor of my controller which will store any return value from the plugin. It's always showing service not found exception.

Please find my plugin code below:

AuthenticationPlugin.php

<?php
namespace Album\Controller\Plugin;

use Zend\Mvc\Controller\Plugin\AbstractPlugin;
use Zend\Session\Container as SessionContainer;
use Zend\View\Model\ViewModel;
use Album\Entity\User;

class AuthenticationPlugin extends AbstractPlugin{

    protected $entityManager;
    protected $usersession;

    public function __construct(){

        $this->usersession = new SessionContainer('UserSession');   
    }

    public function dologin($email,$password)
    {
        $getData = $this->em()->getRepository('Album\Entity\User')->findOneBy(array('email' => $email, 'password' => $password));

        if(count($getData)){

            $this->usersession->offsetSet('userid', $getData->getId());

            return true;
        }
        else{

            return false;
        }   
    }

    public function isloggedin(){

        $userid = $this->usersession->offsetGet('userid');

        if(!empty($userid)){

            return true;    
        }   
        else{

            return false;   
        }
    }

    public function logindata(){

        $userid = $this->usersession->offsetGet('userid');
        $getData = $this->em()->getRepository('Album\Entity\User')->findOneBy(array('id' => $userid));

        return $getData;
    }

    public function logout(){

        $this->usersession->offsetUnset('userid');  
    }

    public function em(){

        return $this->entityManager = $this->getController()->getServiceLocator()->get('Doctrine\ORM\EntityManager');   
    }
}
?>

In my module.config.php

'controller_plugins' => array(
        'invokables' => array(
            'AuthPlugin' => 'Album\Controller\Plugin\AuthenticationPlugin',
        )
    ),

Now I am doing this in my controller:

protected $entityManager;
protected $isloggedin;
protected $authentication;

public function __construct(){

    $this->authentication = $this->AuthPlugin();
    $this->isloggedin = $this->authentication->isloggedin();    
}

The error I am getting is like below:

An error occurred An error occurred during execution; please try again later. Additional information: Zend\ServiceManager\Exception\ServiceNotFoundException

File:

D:\xampp\htdocs\subhasis\zf2-tutorial\vendor\zendframework\zendframework\library\Zend\ServiceManager\ServiceManager.php:555

Message:

Zend\Mvc\Controller\PluginManager::get was unable to fetch or create an instance for AuthPlugin

But if I write the above constructor code in any of my controller actions everything is fine. in ZF1 I could initialize any variable in the init() method and could use the variable in any of my actions. How can I do this in ZF2? Here, I want to detect if the user is logged in the constructor itself. Now I have to call the plugin in every action which I don't want.

What should I do here?

Upvotes: 0

Views: 503

Answers (1)

AlexP
AlexP

Reputation: 9857

The error you are receiving is because you are trying to use the ServiceManager (via the Zend\Mvc\Controller\PluginManager) in the __construct method of the controller.

When a controller is registered as an invokable class, the Service Manager (ControllerManager) is responsible for the creating the controller instance. Once created, it will then call the controllers various default 'initializers' which also inlcudes the plugin manager. By having your code in __construct it is trying to use the plugin manager before it has been set.

You can resolve this by using a controller factory, rather than an invokable in module.config.php.

'controllers' => [
    'factories' => [
        'MyModule\Controller\Foo' => 'MyModule\Controller\FooControllerFactory',
    ],
],

Then the factory

namespace MyModule\Controller\FooControllerFactory;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class FooControllerFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $controllerManager)
    {
        $serviceManager = $controllerManager->getServiceLocator();
        $controllerPluginManager = $serviceManager->get('ControllerPluginManager');

        $authPlugin = $controllerPluginManager->get('AuthPlugin');

        return new FooController($authPlugin);
    }
}

Lastly, update the controller __construct to add the new argument and remove the call to $this->authPlugin()

class FooController extends AbstractActionController
{
    public function __construct(AuthPlugin $authentication)
    {
        $this->authentication = $authentication;
        $this->isloggedin     = $authentication->isloggedin();
    }
}

Upvotes: 1

Related Questions