Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Symfony-如何访问实体&x27;s存储库_Symfony_Design Patterns_Doctrine Orm_Doctrine_Symfony 2.3 - Fatal编程技术网

Symfony-如何访问实体&x27;s存储库

Symfony-如何访问实体&x27;s存储库,symfony,design-patterns,doctrine-orm,doctrine,symfony-2.3,Symfony,Design Patterns,Doctrine Orm,Doctrine,Symfony 2.3,有几种方法可以访问Symfony2控制器或服务中实体的存储库,每种方法都有其优缺点。首先,我在这里列出它们,然后询问是否有更好的解决方案,或者这些是我们唯一的选择,我们应该根据自己的偏好选择一个或一些。我还想知道方法5(我最近开始使用)是否好,是否不违反任何规则或有任何副作用 基本方法:在控制器中使用实体管理器或将其注入服务,然后访问我想要的任何存储库。这是在控制器或服务中访问存储库的基本方法 class DummyController { public function dummyAc

有几种方法可以访问Symfony2控制器或服务中实体的存储库,每种方法都有其优缺点。首先,我在这里列出它们,然后询问是否有更好的解决方案,或者这些是我们唯一的选择,我们应该根据自己的偏好选择一个或一些。我还想知道方法5(我最近开始使用)是否好,是否不违反任何规则或有任何副作用

基本方法:在控制器中使用实体管理器或将其注入服务,然后访问我想要的任何存储库。这是在控制器或服务中访问存储库的基本方法

class DummyController
{
    public function dummyAction($id)
    {
        $em = $this->getDoctrine()->getManager();
        $em->getRepository('ProductBundle:Product')->loadProduct($id);
    }
}
class DummyService
{
    protected $productRepository;

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

    public function dummyFunction($id)
    {
        $this->productRepository->loadProduct($id);
    }
}
但这种方法也存在一些问题。第一个问题是,我不能在按住Ctrl键的同时单击loadProduct函数,然后直接转到它的实现(除非有一种方法我不知道)。另一个问题是,我最终会一遍又一遍地重复这部分代码

方法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');
    }
}
class DummyService
{
    protected $em;

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

    public function dummyFunction($id)
    {
        Product::getRepository($this->em)->loadProduct($id);
    }
}
这个方法解决了第一个问题,也解决了第二个问题,但我还是有 为了重复我在服务或控制器中需要的所有getter,我在服务和控制器中也将有几个getter,它们仅用于访问存储库

方法3:另一种方法是向我的服务中注入存储库,这很好,特别是如果我们对代码有很好的控制,并且我们没有与其他将整个容器注入到您的服务中的开发人员打交道的话

class DummyController
{
    public function dummyAction($id)
    {
        $em = $this->getDoctrine()->getManager();
        $em->getRepository('ProductBundle:Product')->loadProduct($id);
    }
}
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)
    {
        $this->getProductRepository()->loadProduct($id);
    }

    /**
     * @return \ProductBundle\Entity\Repository\ProductRepository
     */
    public function getProductRepository()
    {
        return $this->em->getRepository('ProductBundle:Product');
    }
}
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__);
    }   
}
这个方法解决了第一个和第二个问题,我也不需要定义
访问存储库的服务。我最近用过它,到目前为止,它是我最好的方法。我不认为这个方法会打破实体的规则,因为它是在类范围内定义的,也是如此。但我仍然不确定它是否有副作用。

对我来说,你的建议没有一个是正确的。
因为我不明白您为什么需要为您的实体创建服务。
如果您需要访问该实体,您唯一需要的就是访问条令。
而条令有一种服务(@doctrine)。
由您在构造中准备只访问该实体

要忘记静力学:


您在方法5中提交的内容是不正确的,您的产品实体已经使用getEntityManager()方法通过ProductRepository访问了entityManager。

在条令世界中,实体应该是一个贫乏的getter和setter模型(以及添加或删除),因此注入存储库是错误的

这一切都取决于你想与教义的结合程度。如果您对传递
@doctrine
服务很满意,那么您可以使用以下方法:

$this->repository = $doctrine->getRepository('CmsBundle:Page');
。。但是,正如前面提到的,这将要求您将
@doctrine
服务传递到每个对象中。这意味着,如果您出于任何原因决定不使用条令,您将需要重构所有代码以适应新的方法(不管是什么),但这对您来说可能不是问题。此外,存储库将被类型提示,因此无法保证(除了检查代码中的类是否正确之外)它是正确的服务

在我看来,最干净的方法是创建如下服务:

XML

。。然后,您可以在任何需要的地方传递存储库服务,而无需在实际代码中使用条令服务。使用这种方法,如果您决定脱离条令,您只需要更改服务定义,而不需要重构所有内容。此外,由于您正在创建特定存储库的服务,您可以在
\u构造中使用类型提示来保证注入正确的服务,如:

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

我建议您使用方法4,您的服务将遵循单一责任原则,因为它只做一件事:允许您访问所有存储库

此服务将主要作为其他服务中的依赖项。对于控制器,我建议您使用相同的辅助函数创建自定义控制器基类


关于代码重复,traits可能是解决方案。即使有很多方法,如果您使用“category”中的trait,我也会使用带有接口的存储库服务。它减少了我的代码与条令直接结合的数量,而这实际上是不必要的。服务/对象所需要的只是获得一个适合接口的存储库,而不是获取原则,以获取存储库(它也没有进行类型检查,因此可能没有任何自定义方法)。您肯定不“需要”原则。这就像得到一头牛,而你所需要的只是一些牛奶。Symfony book和cookbook中使用了方法1,你说没有一个是正确的是什么意思。我没有为我的实体创建服务,ProductService只是一个示例,我将其更改为DummyService。您提到的关于静态方法的问题是正确的,但在本例中不同(方法5)。“您的产品实体