ZF2如何在抽象实体类中注入服务定位器或插件

时间:2014-07-08 20:48:28

标签: doctrine-orm zend-framework2 entity abstract-class service-locator

我的Doctrine 2 Entity有一个抽象类。如何注入服务定位器以获取Translator或Zend \ Mvc \ Controller \ Plugin \ Url,或者如何将这些插件直接注入抽象实体类。

目标是从实体存储库中获取学说实体,并在抽象实体模型/服务中操纵实体的结果。

Doctrine 2实体简称:

namespace Rental\Entity;

use Doctrine\ORM\Mapping as ORM;
use Rental\Model\Rental as AbstractRental;

/**
 * Rental
 *
 * @ORM\Entity(repositoryClass="Rental\Repository\Rental") *
 * @ORM\Table(name="rental", options={"collate"="utf8_general_ci"})
 */
class Rental extends AbstractRental{

    ...

    public function getType(){
    ...
    }

    ... entity setter and getter

}

抽象实体模型:

namespace Rental\Model;

use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

/**
 * Rental\Model\Rental
 * @ORM\MappedSuperclass
 * @ORM\HasLifecycleCallbacks
 */
abstract class Rental implements ServiceLocatorAwareInterface
{
    protected $serviceLocator;
    protected $translator;

    abstract protected function getType();

    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
    }

    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }

    public function getTranslator()
    {
        if (!$this->translator) {
            $this->translator = $this->getServiceLocator()->get('translator');
            // here is the problem, because getServiceLocator is NULL
        }

        return $this->translator;
    }

    public function getTranslatedType(){            
        return $this->translator->translate($this->getType())
    }

这不起作用,因为抽象类没有实例化,因此不会注入ServiceLocatorInterface。

这是我的控制器:

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;  
use Doctrine\ORM\EntityManager;


namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;  
use Doctrine\ORM\EntityManager;


class IndexController extends AbstractActionController
{
    /**
     * @var \Doctrine\ORM\EntityManager
     */
    protected $em;


    /**
     * @param \Doctrine\ORM\EntityManager $em
     */
    public function setEntityManager(EntityManager $em)
    {
        $this->em = $em;
    }


    /**
     * @return array|\Doctrine\ORM\EntityManager|object
     */
    public function getEntityManager()
    {
        if (NULL === $this->em) {
            $this->em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
        }

        return $this->em;
    }


    /**
     * @return \Zend\View\Model\ViewModel
     */
    public function indexAction()
    {
        ...

        /** @var $repository \Rental\Repository\Rental */
        $repository = $this->getEntityManager()->getRepository('Rental\Entity\Rental');

        /** @var $rentals array */
        $rental= $repository->findBySlug($slug);
        \ChromePhp::log($rental->getTranslatedType()); 
        // is NULL

1 个答案:

答案 0 :(得分:-1)

这是实现将ZF2服务定位器注入从抽象类继承的实体的目标的一种方法

请记住更改/修复任何名称空间

首先,您需要使用Doctrine注册事件监听器。您只需要监听 postLoad 。为此,实例化侦听器(我们接下来将定义)并将其传递给它唯一的依赖项,即服务定位器。

Module.php

// in your Module.php
use Rental\Model\Listeners\EntityInjectorListener;

public function onBootstrap(MvcEvent $e)
{
    $serviceLocator = $e->getApplication()->getServiceManager();
    $entityManager = $serviceLocator->get('Doctrine\ORM\EntityManager');
    $entityManager->getEventManager()->addEventListener(array(\Doctrine\ORM\Events::postLoad), new EntityInjectorListener($serviceLocator));
}

现在为Doctrine定义一个侦听器。它应该检查它正在处​​理的实体,如果它继承自你的抽象类,那么它应该设置服务定位器。

//  EntityInjectorListener.php
namespace \Rental\Model\Listeners;

class EntityInjectorListener
{
    protected $serviceLocator;

    public function __construct($serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
    }

     public function postLoad($eventArgs) 
     {
        // check if entity is a child of abstract class
        if ($eventArgs->getEntity() instanceof \Rental\Model\Rental) {
            $eventArgs->getEntity()->setServiceLocator($this->serviceLocator);
        }
     }
}

现在你的实体内你应该可以打电话给 $this->getServiceLocator()->get('whatever-you-want-get');

要使用视图助手,您需要像这样调用它们:

$this->getServiceLocator()->get('ViewHelperManager')->get('url');