18

我正在学习 Symfony,并且一直在尝试使用存储库创建服务。我已经从 generate:entity 创建了我的存储库和实体,所以它们应该没问题。

到目前为止,我在 services.yml 中得到的是:

parameters:
    mytest.entity: TestTestBundle:Brand
    mytest.class:  Test\TestBundle\Entity\Brand
    default_repository.class: Doctrine\ORM\EntityRepository

services:
     myservice:
          class: %default_repository.class%
          factory-service: doctrine.orm.default_entity_manager
          factory-method: getRepository
          arguments:
            - %mytest.entity%

但是当我尝试调用服务时,我收到了这个错误:

Catchable Fatal Error: Argument 2 passed to Doctrine\ORM\EntityRepository::__construct() must be an instance of Doctrine\ORM\Mapping\ClassMetadata, none given, called in 

然后我尝试仅使用实体创建服务。我的 services.yml 看起来像:

services:
     myservice:
          class: %mytest.class%
          factory-service: doctrine.orm.default_entity_manager
          factory-method: getRepository
          arguments:
            - %mytest.entity%

但为此,我得到:

Error: Call to undefined method 
                Test\TestBundle\Entity\Brand::findAll

有人知道我在做什么错吗?

谢谢

4

7 回答 7

44

弃用警告:没有更多factory_servicefactory_method. 从Symfony 2.6开始,你应该这样做(对于Symfony 3.3+ ,请查看下方):

parameters:
    entity.my_entity: "AppBundle:MyEntity"

services:
    my_entity_repository:
        class: AppBundle\Repository\MyEntityRepository
        factory: ["@doctrine", getRepository]
        arguments:
            - %entity.my_entity%

Symfony 2.6 中引入了新的setFactory()方法。有关 2.6 之前的工厂的语法,请参阅旧版本。

http://symfony.com/doc/2.7/service_container/factories.html

编辑:看起来他们一直在改变这个,所以从Symfony 3.3开始有一个新的语法:

# app/config/services.yml
services:
    # ...

    AppBundle\Email\NewsletterManager:
        # call the static method
        factory: ['AppBundle\Email\NewsletterManagerStaticFactory', createNewsletterManager]

看看:http ://symfony.com/doc/3.3/service_container/factories.html

于 2015-08-04T11:04:44.927 回答
24

以下是我们在 KnpRadBundle 中的做法:https ://github.com/KnpLabs/KnpRadBundle/blob/develop/DependencyInjection/Definition/DoctrineRepositoryFactory.php#L9

最后应该是:

my_service:
    class: Doctrine\Common\Persistence\ObjectRepository
    factory_service: doctrine # this is an instance of Registry
    factory_method: getRepository
    arguments: [ %mytest.entity% ]

更新

从 2.4 开始,学说允许覆盖默认的存储库工厂。

这是在 symfony 中实现它的一种可能方法:https ://gist.github.com/docteurklein/9778800

于 2013-06-21T08:00:02.157 回答
10

您可能使用了错误的 YAML 密钥。你的第一个配置对我来说很好用

  • factory_service 而不是 factory-service
  • factory_method 而不是 factory-method
于 2013-11-17T16:06:44.643 回答
2

自 2017 年和 Symfony 3.3+ 以来,这变得容易多了。

注意:尽量避免使用通用命令,例如generate:entity. 它们是为初学者设计的,可以使项目快速工作。他们倾向于暴露不好的做法,并且需要很长时间才能改变。

查看我的帖子How to use Repository with Doctrine as Service in Symfony以获得更一般的描述。

到您的代码:

1. 更新您的配置注册以使用基于 PSR-4 的自动注册

# app/config/services.yml
services:
    _defaults:
        autowire: true

    Test\TestBundle\:
        resource: ../../src/Test/TestBundle

2. 组合优于继承 - 创建自己的存储库而不直接依赖于 Doctrine

<?php

namespace Test\TestBundle\Repository;

use Doctrine\ORM\EntityManagerInterface;

class BrandRepository
{
    private $repository;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->repository = $entityManager->getRepository(Brand::class);
    }

    public function findAll()
    {
        return $this->repository->findAll();
    }
}

3. 通过构造函数注入在任何服务或控制器中使用

use Test\TestBundle\Repository\BrandRepository;

class MyController
{
    /**
     * @var BrandRepository
     */
    private $brandRepository;

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

    public function someAction()
    {
        $allBrands = $this->brandRepository->findAll();
        // ...
    }

}
于 2017-10-21T11:23:18.947 回答
0

我将 service.yml 转换为 service.xml,并更新 DependencyInjection Extension,一切都为我工作。我不知道为什么,但是 yml 配置会抛出 Catchable Fatal Error。您可以尝试使用 xml config 进行服务配置。

服务.yml:

services:
    acme.demo.apikey_userprovider:
        class: Acme\DemoBundle\Entity\UserinfoRepository
        factory-service: doctrine.orm.entity_manager
        factory-method: getRepository
        arguments: [ AcmeDemoBundle:Userinfo ]

    acme.demo.apikey_authenticator:
        class: Acme\DemoBundle\Security\ApiKeyAuthenticator
        arguments: [ "@acme.demo.apikey_userprovider" ]

服务.xml:

<services>
    <service id="acme.demo.apikey_userprovider" class="Acme\DemoBundle\Entity\UserinfoRepository"  factory-service="doctrine.orm.entity_manager" factory-method="getRepository">
        <argument>AcmeDemoBundle:Userinfo</argument>
    </service>

    <service id="acme.demo.apikey_authenticator" class="Acme\DemoBundle\Security\ApiKeyAuthenticator">
        <argument type="service" id="acme.demo.apikey_userprovider" />
    </service>
</services>
于 2014-07-17T07:09:40.347 回答
0

Symfony 3.3教义捆绑 1.8有一个Doctrine\Bundle\DoctrineBundle\Repository\ContainerRepositoryFactory 有助于将存储库创建为服务。

例子

我们想要什么

$rep = $kernel->getContainer()
    ->get('doctrine.orm.entity_manager')
    ->getRepository(Brand::class);

ORM 描述

# Brand.orm.yaml
...
repositoryClass: App\Repository\BrandRepository
...

服务说明

# service.yaml

App\Repository\BrandRepository:
    arguments:
      - '@doctrine.orm.entity_manager'
      - '@=service("doctrine.orm.entity_manager").getClassMetadata("App\\Entity\\Brand")'
    tags:
        - { name: doctrine.repository_service }
    calls:
        - method: setDefaultLocale
          arguments:
              - '%kernel.default_locale%'
        - method: setRequestStack
          arguments:
              - '@request_stack'
于 2017-11-18T09:51:30.817 回答
-2

2.6+

parameters:
    mytest.entity: TestTestBundle:Brand
    mytest.class:  Test\TestBundle\Entity\Brand
    default_repository.class: Doctrine\ORM\EntityRepository

services:
     myservice:
          class: %default_repository.class%
          factory: ["@doctrine.orm.default_entity_manager", "getRepository"]
          arguments:
            - %mytest.entity%
于 2016-02-08T13:10:33.350 回答