ZF2 Controller Plugin

2020-03-28 17:09发布

I'm new to ZF2 and am having some trouble with what should be a basic idea.

I'm using the ZfCommons User module for authentication, it's been installed and is operating properly.

Now I want validate the user is in fact logged in from my controller based on this (How to check if the user is logged in but I can't figure out out how to register the controller plugin, I'm currently receiving this error:

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

My Controller looks like this:

<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController as AbstractActionController;
use Zend\View\Model\ViewModel as ViewModel;

class IndexController extends AbstractActionController
{

    public function __construct()
    {
        $plugin = $this->plugin('ZfcUserAuthentication');

    }

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

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

2条回答
兄弟一词,经得起流年.
2楼-- · 2020-03-28 17:56

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.

查看更多
3楼-- · 2020-03-28 17:56

According to the docs, you can use the following

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

$this->zfcUserAuthentication()->getIdentity()
查看更多
登录 后发表回答