Symfony2:如何从存储库访问服务

Ala*_*tor 10 php symfony

我有类ModelsRepository:

class ModelsRepository extends EntityRepository
{}
Run Code Online (Sandbox Code Playgroud)

和服务

container_data:
 class:        ProjectName\MyBundle\Common\Container
 arguments:    [@service_container]
Run Code Online (Sandbox Code Playgroud)

我想从ModelsRepository访问service_data.我无法从控制器使用的构造函数传输服务.

你知道怎么做吗?

Tou*_*uki 13

恕我直言,这不应该是需要的,因为你可能很容易违反像SRPDemeter法则这样的规则

但如果你真的需要它,这是一种方法:

首先,我们定义一个基础"ContainerAwareRepository"类,它有一个调用"setContainer"

services.yml

services:
    # This is the base class for any repository which need to access container
    acme_bundle.repository.container_aware:
        class: AcmeBundle\Repository\ContainerAwareRepository
        abstract: true
        calls:
            - [ setContainer, [ @service_container ] ]
Run Code Online (Sandbox Code Playgroud)

ContainerAwareRepository可能如下所示

AcmeBundle\Repository\ContainerAwareRepository.php

abstract class ContainerAwareRepository extends EntityRepository
{
    protected $container;

    public function setContainer(ContainerInterface $container)
    {
        $this->container = $container;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,我们可以定义我们的模型库.
我们在这里使用了doctrine的getRepository方法来构建我们的存储库

services.yml

services:
    acme_bundle.models.repository:
        class: AcmeBundle\Repository\ModelsRepository
        factory_service: doctrine.orm.entity_manager
        factory_method:  getRepository
        arguments:
            - "AcmeBundle:Models"
        parent:
            acme_bundle.repository.container_aware
Run Code Online (Sandbox Code Playgroud)

然后,只需定义类

AcmeBundle\Repository\ModelsRepository.php

class ModelsRepository extends ContainerAwareRepository
{
    public function findFoo()
    {
        $this->container->get('fooservice');
    }
}
Run Code Online (Sandbox Code Playgroud)

为了使用存储库,您绝对需要首先从服务中调用它.

$container->get('acme_bundle.models.repository')->findFoo(); // No errors
$em->getRepository('AcmeBundle:Models')->findFoo(); // No errors
Run Code Online (Sandbox Code Playgroud)

但如果你直接做

$em->getRepository('AcmeBundle:Models')->findFoo(); // Fatal error, container is undefined
Run Code Online (Sandbox Code Playgroud)


Ita*_*ako 8

永远不应该将容器传递给存储库,就像您永远不应该让实体处理繁重的逻辑一样.存储库只有一个目的 - 从数据库中检索数据.没有更多(阅读:http://docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html).

如果您需要比这更复杂的东西,您应该为此创建一个单独的(如果您愿意的容器).


Ala*_*tor 7

我试过一些版本.问题解决了

ModelRepository:

class ModelRepository extends EntityRepository
{
    private $container;

    function __construct($container, $em) {
        $class = new ClassMetadata('ProjectName\MyBundle\Entity\ModelEntity');
        $this->container = $container;

        parent::__construct($em, $class);
    }
}
Run Code Online (Sandbox Code Playgroud)

security.yml:

providers:
    default:
        id: model_auth
Run Code Online (Sandbox Code Playgroud)

services.yml

model_auth:
    class: ProjectName\MyBundle\Repository\ModelRepository
    argument
Run Code Online (Sandbox Code Playgroud)

结果我得到了能力使用容器的存储库 - 根据需要.但是这种实现只能在关键情况下使用,因为她对Repository有限制.Thx 4all.