在Symfony2的控制器或服务中,我们可以通过几种方式访问实体的存储库,每种方式都有其优点和缺点。首先我在这里列出它们,然后询问是否有更好的解决方案,或者这些是我们唯一的选择,我们应该根据自己的喜好选择其中的一个或几个。我还想知道最近我开始使用的第五种方法是否可行,是否符合规则,是否有任何副作用。
基本方法:在控制器中使用实体管理器或将其注入到服务中,然后访问我想要的任何存储库。这是访问控制器或服务中存储库的基本方式。
class DummyController
{
public function dummyAction($id)
{
$em = $this->getDoctrine()->getManager();
$em->getRepository('ProductBundle:Product')->loadProduct($id);
}
}
但是,这种方法存在一些问题。第一个问题是,例如在loadProduct函数上无法使用Ctrl + 单击直接进入其实现(除非有我不知道的方法)。另一个问题是,我最终会反复重复这部分代码。
方法2:另一种方法就是在我的服务或控制器中定义一个getter来访问我的存储库。
class DummyService
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function dummyFunction($id)
{
$this->getProductRepository()->loadProduct($id);
}
/**
* @return \ProductBundle\Entity\Repository\ProductRepository
*/
public function getProductRepository()
{
return $this->em->getRepository('ProductBundle:Product');
}
}
该方法解决了第一个问题,某种程度上也解决了第二个问题,但仍然需要在我的服务或控制器中重复所有需要的getter,而且我将有多个getter在我的服务和控制器中,仅用于访问存储库。方法3:另一种方法是将存储库注入到我的服务中,这很好,特别是如果我们对代码有很好的控制,并且不与将整个容器注入到您的服务中的其他开发人员一起工作。
class DummyService
{
protected $productRepository;
public function __construct(ProductRepository $productRepository)
{
$this->productRepository = $productRepository;
}
public function dummyFunction($id)
{
$this->productRepository->loadProduct($id);
}
}
这种方法可以解决第一和第二个问题,但如果我的服务很大并且需要处理很多存储库,那么将10个存储库注入到我的服务中就不是一个好主意。
方法4:另一种方法是创建一个服务来包装所有的存储库,并将这个服务注入到其他服务中。
class DummyService
{
protected $repositoryService;
public function __construct(RepositoryService $repositoryService)
{
$this->repositoryService = $repositoryService;
}
public function dummyFunction($id)
{
$this->repositoryService->getProductRepository()->loadProduct($id);
}
}
仓库服务:
class RepositoryService
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
/**
* @return \ProductBundle\Entity\Repository\ProductRepository
*/
public function getProductRepository()
{
return $this->em->getRepository('ProductBundle:Product');
}
/**
* @return \CmsBundle\Entity\Repository\PageRepository
*/
public function getPageRepository()
{
return $this->em->getRepository('CmsBundle:Page');
}
}
这种方法也解决了第一个和第二个问题。但是当我们有200个实体时,RepositoryService可能会变得非常大。
方法5:最后,我可以在每个实体中定义一个静态方法来返回其存储库。
class DummyService
{
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function dummyFunction($id)
{
Product::getRepository($this->em)->loadProduct($id);
}
}
我的实体:
/**
* Product
*
* @ORM\Table(name="saman_product")
* @ORM\Entity(repositoryClass="ProductBundle\Entity\ProductRepository")
*/
class Product
{
/**
*
* @param \Doctrine\ORM\EntityManagerInterface $em
* @return \ProductBundle\Entity\ProductRepository
*/
public static function getRepository(EntityManagerInterface $em)
{
return $em->getRepository(__CLASS__);
}
}
这种方法解决了第一个和第二个问题,而且我不需要定义服务来访问存储库。我最近使用过它,到目前为止,这是对我最好的方法。我认为这种方法不会违反实体规则,因为它在类范围内定义,并且非常精简。但是我仍然不确定它是否有任何副作用。