Doctrine orm 如何为EntityManager创建通用模型?

Doctrine orm 如何为EntityManager创建通用模型?,doctrine-orm,zend-framework2,Doctrine Orm,Zend Framework2,我正在尝试使用ZF2和Doctrine 2创建一些东西。但我有点迷失了我想要实现的目标 首先,我现在使用$em=$this->getServiceLocator->get'Doctrine\ORM\EntityManager';在控制器内部,它将工作 但我想要的是更详细的东西,比如: class BaseModel extends Doctrine\ORM\EntityManager { public function save() { $em->persist($this

我正在尝试使用ZF2和Doctrine 2创建一些东西。但我有点迷失了我想要实现的目标

首先,我现在使用$em=$this->getServiceLocator->get'Doctrine\ORM\EntityManager';在控制器内部,它将工作

但我想要的是更详细的东西,比如:

class BaseModel extends Doctrine\ORM\EntityManager
{
  public function save()
  {
    $em->persist($this);
    $em->flush();
  }
}

/**
 * @ORM\Entity
 */
class Customer extends BaseModel
{
  // getters setters
}

class IndexController
{
  public function indexAction()
  {
    $customer = new Customer();
    $customer->setName('asd');
    $customer->save();

    Customer::findAll();
  }
}
我已经开始这样做:

namespace Ws\Model;

use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorAwareTrait;

class BaseModel implements ServiceLocatorAwareInterface
{
  use ServiceLocatorAwareTrait;

  public function write() {
        $em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
        return $em->getRepository(__CLASS__);
    }
}
但是没有成功

我知道这不仅仅是一个问题,但它是否有可能在这里帮助我,甚至通过一些链接,可以帮助我在这个旅程


谢谢。

您有没有看过Zend\ServiceManager\ServiceLocatorAwaRetrit的实现?它只是给你,但当然,如果你不设定它,你永远不会得到它。所以$this->getServiceLocator将始终返回null


你最好使用依赖注入,不要注入服务定位器,而是注入所需的服务,或者,正如@Cerad所指出的那样,按照设计的方式使用条令。

你很幸运。我自己刚刚创建了一个用于我自己的供应商包

虽然您的代码很混乱,但我将假设您引用的模型是实体,而不是实体和存储库的组合

但是,要遵守代码

请特别注意名称空间,并相应地组织文件夹结构和文件名

文件:repoName/src/Entity/AbstractEntity.php

<?php
namespace Company\Core;

use Doctrine\ORM\Mapping as ORM;
use Company\Core\Listener\ServiceLocatorAwareEntity;

/**
 * Class AbstractEntity
 * @package Company\Core\Entity
 *
 * @ORM\MappedSuperclass
 * @ORM\HasLifecycleCallbacks
 */
abstract class AbstractEntity extends ServiceLocatorAwareEntity
{
    /**
     * @var int
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param int $id
     * @return AbstractEntity
     */
    public function setId($id)
    {
        $this->id = $id;
        return $this;
    }
}
<?php

namespace Company\Core\Listener;

use Zend\Di\ServiceLocator;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class ServiceLocatorAwareEntity implements ServiceLocatorAwareInterface
{
    protected $sm;

    /**
     * Set the service locator
     *
     * @param ServiceLocatorInterface $sm
     *
     * @return void
     */
    public function setServiceLocator(ServiceLocatorInterface $sm)
    {
        $this->sm = $sm;
    }

    /**
     * Get the service locator
     *
     * @return ServiceLocator ServiceLocator instance
     */
    public function getServiceLocator()
    {
        return $this->sm;
    }
}
由于此设置,请确保将@ORM\HasLifecycleCallbacks原则注释添加到实体类。上面的函数触发ServiceManagerListener的添加,这反过来又触发其余的

现在剩下的就是在您自己的模块中使用它。如果需要,请无休止地重复:

这里我们回到应用程序本身。 确保对每个实体和控制器执行以下操作,您应该会没事

创建以下内容:

<?php

namespace Application\Service;

use Company\Core\Service\AbstractEntityService;

class IndexControllerService extends AbstractEntityService
{
    //Yes really, this class is empty. Extends an Abstract class which may not be directly instantiated.
}
'controllers' => [
    'factories' => [
        IndexController::class => IndexControllerFactory::class,
    ],
],
'service_manager' => [
    'invokables' => [
        IndexControllerService::class => IndexControllerService::class,
    ],
],

好了,应该准备好了

如果您想要一个活动记录实现,那么使用一个基于活动记录的orm,比如propel或Elount。我相信采埃孚有办法将其融入其中。试图使用数据映射器(如信条)将导致无尽的挫折。按照设计的方式使用条令如何?可能会对它的威力感到惊讶。它是目前为止最流行的orm是有原因的。
public function onBootstrap(MvcEvent $e)
{
    $sm = $e->getApplication()->getServiceManager();
    /** @var EntityManager $em */
    $em = $sm->get('doctrine.entitymanager.orm_default');

    /** @var \Doctrine\Common\EventManager $dem */
    $dem = $em->getEventManager();
    /**
     * Binds adding EventListener "ServiceManagerListener" to the Doctrine Event PostLoad
     */
    $dem->addEventListener([Events::postLoad], new ServiceManagerListener($sm));
}
<?php

namespace Application\Service;

use Company\Core\Service\AbstractEntityService;

class IndexControllerService extends AbstractEntityService
{
    //Yes really, this class is empty. Extends an Abstract class which may not be directly instantiated.
}
<?php

namespace Application\Factory;

use Application\Controller\IndexController;
use Application\Service\IndexControllerService;
use Doctrine\ORM\EntityManager;
use Zend\Mvc\Controller\ControllerManager;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\ServiceManager;

class IndexControllerFactory implements FactoryInterface
{
    /**
     * @param ServiceLocatorInterface|ControllerManager $serviceLocator
     * @return IndexController
     */
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        /** @var ServiceManager $serviceManager */
        $serviceManager = $serviceLocator->getServiceLocator();
        /** @var EntityManager $entityManager */
        $entityManager = $serviceManager->get('doctrine.entitymanager.orm_default');
        /** @var IndexControllerService $entityService */
        $entityService = new IndexControllerService($entityManager);
        /** @var IndexController $controller */
        $controller = new IndexController($entityService);

        return $controller;
    }
}
<?php

namespace Application\Controller;

use Company\Core\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return [];
    }
}
'controllers' => [
    'factories' => [
        IndexController::class => IndexControllerFactory::class,
    ],
],
'service_manager' => [
    'invokables' => [
        IndexControllerService::class => IndexControllerService::class,
    ],
],