【问题标题】:ZF2 getServiceLocator in ControllerPlugin classControllerPlugin 类中的 ZF2 getServiceLocator
【发布时间】:2012-09-14 09:20:29
【问题描述】:

我正在尝试在插件类中获取服务定位器/实体管理器,我怎样才能得到它。

在我的控制器中,我得到了这样的结果。

public function getEntityManager()
{
    if(null === $this->em){
        $this->em = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
    }
    return $this->em;
}

public function setEntityManager(EntityManager $em)
{
    $this->em = $em;
}

但在插件类中,我在 $this->getServiceLocator() 行上遇到错误。因为这在插件类中不可用。

我怎样才能做到这一点,以便我可以获取一些记录并在插件中的数据库中插入一些记录。

我的插件类中确实有 MvcEvent $e 对象,我可以利用它来获取实体管理器吗?

我使用this plugin 来创建我的插件

任何指南都会被应用。

更新:

namespace Auth\Controller\Plugin;

use Zend\Mvc\Controller\Plugin\AbstractPlugin;
use Zend\EventManager\EventInterface as Event;
use Zend\Authentication\AuthenticationService;

use Doctrine\ORM\EntityManager;
use Auth\Entity\User;
use Zend\Mvc\MvcEvent;
class AclPlugin extends AbstractPlugin
{

    /*
    * @var Doctrine\ORM\EntityManager
    */
    protected $em;

    public function checkAcl($e)
    {

        $auth = new AuthenticationService();
        if ($auth->hasIdentity()) {
            $storage = $auth->getStorage()->read();            
            if (!empty($storage->role))
                $role = strtolower ( $storage->role );            
            else 
                $role = "guest";            
        } else {
            $role = "guest";            
        }
        $app = $e->getParam('application');
        $acl          = new \Auth\Acl\AclRules(); 

        $matches      = $e->getRouteMatch();
        $controller   = $matches->getParam('controller');
        $action       = $matches->getParam('action', 'index');

        $resource = strtolower( $controller );
        $permission = strtolower( $action );

        if (!$acl->hasResource($resource)) {
            throw new \Exception('Resource ' . $resource . ' not defined');
        }

        if ($acl->isAllowed($role, $resource, $permission)) {

            $query = $this->getEntityManager($e)->createQuery('SELECT u FROM Auth\Entity\User u');
            $resultIdentities = $query->execute();

            var_dump($resultIdentities);
            exit();


            return;

        } else {
            $matches->setParam('controller', 'Auth\Controller\User'); // redirect
            $matches->setParam('action', 'accessdenied');    

            return;
        }


    }


    public function getEntityManager($e) {

        var_dump($this->getController()); // returns null
        exit();
        if (null === $this->em) {
            $this->em = $this->getController()->getServiceLocator()->get('doctrine.entitymanager.orm_default');

        }
        return $this->em;
    }

    public function setEntityManager(EntityManager $em) {
        $this->em = $em;
    }

}

我在module.php中调用上面的类

    public function onBootstrap(Event $e) 
    {

        $application = $e->getApplication();        
        $services    = $application->getServiceManager();        

        $eventManager = $e->getApplication()->getEventManager();
        $eventManager->attach('dispatch', array($this, 'loadConfiguration'),101);

    }

public function loadConfiguration(MvcEvent $e)
    {

        $e->getApplication()->getServiceManager()
                  ->get('ControllerPluginManager')->get('AclPlugin')
                  ->checkAcl($e); //pass to the plugin...      

    }

我在 module.config.php 中注册了这个插件

return array(  
 'controllers' => array(
        'invokables' => array(
            'Auth\Controller\User' => 'Auth\Controller\UserController',
        ),
    ), 

    'controller_plugins' => array(
      'invokables' => array(
          'AclPlugin' => 'Auth\Controller\Plugin\AclPlugin',
      ),  
    ),
);

【问题讨论】:

    标签: php zend-framework2


    【解决方案1】:

    “插件类”是什么意思?如果您正在谈论控制器插件,您可以使用(从控制器插件的范围)访问它:$this->getController()->getServiceLocator()->get('doctrine.entitymanager.orm_default');

    对于其他类,我通常会创建一个自动注入 ServiceManager 实例的工厂。例如在 Module 类中:

    public function getServiceConfig()
    {
        return array(
            'factories' => array(
                'myServiceClass' => function(ServiceManager $sm) {
                    $instance = new Class();
                    $instance->setServiceManager($sm);
                    // Do some other configuration
    
                    return $instance;
                },
            ),
        );
    }
    
    // access it using the ServiceManager where you need it
    $myService = $sm->get('myService');
    

    【讨论】:

    • 插件类在 controller\Plugin\ 下并且可以通过使用返回数组 ('controller_plugins' => array('invokables' => array('AclPlugin' => 'Auth\Controller\Plugin\ AclPlugin', ), ), );但不知何故,当我使用 $this->getController()->getServiceLocator()->get('doctrine.entitymanager.orm_default');在插件类中的错误是致命错误:调用 /module/Auth/src/Auth/Controller/Plugin/AclPlugin.php 中的非对象上的成员函数 getServiceLocator()
    • 你能粘贴你的控制器插件类吗?我这样做的方式完全相同,它对我有用。另外,请说明您的 ZF2 版本(betaN/RCn/2.0.0)。
    • 版本是 zf2 stable relase 2.0.0。请参阅上面有问题的课程
    • 你如何使用/调用这个类?
    • 哦——好的,这就是问题所在。控制器插件旨在用于控制器内部。它们实现了一个可插入的方法模式,并且可以在控制器上下文中使用$this->pluginName()->doSomething 调用。在这种情况下,控制器插件系统负责实例化并分配控制器实例。但是,您可以在该类中实现 ServiceManagerAwareInterface 并在调用 checkAcl 方法之前从模块中注入 ServiceManager..
    【解决方案2】:

    将上面的 AclPlugin 类更改如下

    namespace Auth\Controller\Plugin;
    
    use Zend\Mvc\Controller\Plugin\AbstractPlugin;
    use Zend\EventManager\EventInterface as Event;
    use Zend\Authentication\AuthenticationService;
    
    use Doctrine\ORM\EntityManager;
    use Auth\Entity\User;
    use Zend\Mvc\MvcEvent;
    
    use Zend\ServiceManager\ServiceManagerAwareInterface;
    use Zend\ServiceManager\ServiceManager;
    class AclPlugin extends AbstractPlugin implements ServiceManagerAwareInterface
    {
    
       /*
        * @var Doctrine\ORM\EntityManager
        */
        protected $em;
    
        protected $sm;
    
        public function checkAcl($e)
        {
    
            $this->setServiceManager( $e->getApplication()->getServiceManager() );
    
            $auth = new AuthenticationService();
            if ($auth->hasIdentity()) {
                $storage = $auth->getStorage()->read();            
                if (!empty($storage->role))
                    $role = strtolower ( $storage->role );            
                else 
                    $role = "guest";            
            } else {
                $role = "guest";            
            }
            $app = $e->getParam('application');
            $acl          = new \Auth\Acl\AclRules(); 
    
            $matches      = $e->getRouteMatch();
            $controller   = $matches->getParam('controller');
            $action       = $matches->getParam('action', 'index');
    
            $resource = strtolower( $controller );
            $permission = strtolower( $action );
    
            if (!$acl->hasResource($resource)) {
                throw new \Exception('Resource ' . $resource . ' not defined');
            }
    
            if ($acl->isAllowed($role, $resource, $permission)) {
    
                $query = $this->getEntityManager($e)->createQuery('SELECT u FROM Auth\Entity\User u');
                $resultIdentities = $query->execute();
    
                var_dump($resultIdentities);
                foreach ($resultIdentities as $r)
                    echo $r->username;
                exit();
    
    
                return;
    
            } else {
                $matches->setParam('controller', 'Auth\Controller\User'); // redirect
                $matches->setParam('action', 'accessdenied');    
    
                return;
            }
    
        }
    
    
    
        public function getEntityManager() {
    
            if (null === $this->em) {
                $this->em = $this->sm->getServiceLocator()->get('doctrine.entitymanager.orm_default');
    
            }
            return $this->em;
        }
    
        public function setEntityManager(EntityManager $em) {
            $this->em = $em;
        }
    
       /**
        * Retrieve service manager instance
        *
        * @return ServiceManager
        */
        public function getServiceManager()
        {
            return $this->sm->getServiceLocator();
        }
    
        /**
        * Set service manager instance
        *
        * @param ServiceManager $locator
        * @return void
        */
        public function setServiceManager(ServiceManager $serviceManager)
        {
            $this->sm = $serviceManager;
        } 
    
    }
    

    【讨论】:

      【解决方案3】:

      其实在控制器插件中获取ServiceManager是很简单的!

      只需使用:$this->getController()->getServiceLocator()

      例子:

      namespace Application\Controller\Plugin;
      
      use Zend\Mvc\Controller\Plugin\AbstractPlugin;
      
      class Translate extends AbstractPlugin 
      {
      
          public function __invoke($message, $textDomain = 'default', $locale = null) 
          {
              /** @var \Zend\I18n\Translator\Translator $translator */
              $translator = $this->getController()->getServiceLocator()->get('translator');
      
              return $translator->translate($message, $textDomain, $locale);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2015-12-25
        • 2023-03-19
        • 1970-01-01
        • 2013-04-03
        • 2013-02-01
        • 1970-01-01
        • 2017-08-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多