ZF2 Controller Plugin

淺唱寂寞╮ 提交于 2019-12-01 10:52:12

The exception is thrown because you are requesting the plugin in the constructor. Because of how plugins are tied to controllers, it is simply not possible to use plugins inside the constructor of the controller.

Background

The constructor is called first when an object is created. There is no other method called before __construct(). If you inject something in this new instance via a setter method, you therefore have no access to this in the constructor.

A code example:

$obj = new MyClass();
$obj->setFoo('foo');

class MyClass()
{
  protected $foo;

  public function __construct()
  {
    var_dump($this->foo); // null!
  }

  public function setFoo($foo)
  {
    $this->foo = $foo;
  }
}

This seems obvious, but it is exactly what is going on in Zend Framework 2 with controllers and the controller plugin manager. The manager is injected after the object is created:

$controller = new MySomethingController;
$controller->setPluginManager($plugins);

See also the code which injects the plugin manager in the controller on Github. Thus: you do not have access to the plugins in your constructor, unfortunately.

Alternative

You can access the plugins in any action you have:

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        // This works!
        $plugin = $this->plugin('ZfcUserAuthentication');

        return new ViewModel();
    }

    public function testAction()
    {
        // This works too!
        $plugin = $this->plugin('ZfcUserAuthentication');

        return new ViewModel();
    }
}

You can also attach a listener to the dispatch of the controller, so a function call is made for every action, not the ones you specify:

use Zend\Mvc\MvcEvent;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
       return new ViewModel();
    }

    public function testAction()
    {
        return new ViewModel();
    }

    protected function attachDefaultListeners()
    {
        parent::attachDefaultListeners();

        $events = $this->getEventManager();
        $events->attach(MvcEvent::EVENT_DISPATCH, array($this, 'checkUserIdentity'));
    }

    public function checkUserIdentity()
    {
        // This works!
        // It is called for both indexAction() and testAction()
        $plugin = $this->plugin('ZfcUserAuthentication');
    }
}

You can even remove this logic out of the controller, so you can reuse it for multiple controllers:

class Module
{
    public function onBootstrap($e)
    {
        $app = $e->getApplication();
        $em  = $app->getEventManager()->getSharedManager();

        $em->attach('MyModule\Controller\MyController', MvcEvent::EVENT_DISPATCH, function($e) {
            $controller = $e->getController();

            // This works!
            $plugin = $controller->plugin('ZfcUserAuthentication');
        });
    }
}

So, depending on how DRY you want it, there are many possibilities to access the plugin outside the constructor.

According to the docs, you can use the following

$this->zfcUserAuthentication()->hasIdentity()

$this->zfcUserAuthentication()->getIdentity()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!