web-dev-qa-db-ja.com

symfony 2:リポジトリからサービスを作成する

私は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

誰かが私が間違っていることを知っていますか?

ありがとう

17
Strnm

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以降、doctrineを使用すると、デフォルトのリポジトリファクトリをオーバーライドできます。

これをsymfonyで実装する可能な方法は次のとおりです: https://Gist.github.com/docteurklein/97788

24
Florian Klein

廃止の警告:もうfactory_serviceおよびfactory_methodSymfony 2.6(forSymfony 3.3 +以下を確認してください):

parameters:
    entity.my_entity: "AppBundle:MyEntity"

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

新しい setFactory() メソッドはSymfony 2.6で導入されました。 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

44

間違ったYAMLキーを使用した可能性があります。あなたの最初の設定は私が使うのにうまくいきます

  • factory-serviceの代わりにfactory_service
  • factory-methodの代わりにfactory_method
10
Daniel

2017年とSymfony 3.3以降以降、これははるかに簡単になりました。

注:generate:entityなどの一般的なコマンドは避けてください。彼らは初心者がプロジェクトを迅速に動作させるために運命づけられています。彼らは悪い習慣を暴露する傾向があり、変更に非常に長い時間がかかります。

私の投稿を確認してください 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();
        // ...
    }

}
2
Tomáš Votruba

Symfony 3.およびdoctrine-bundle 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'
0
Vladimir Pak

Service.ymlをservice.xmlに変換し、DependencyInjection Extensionを更新すると、すべてがうまくいきます。理由はわかりませんが、yml configがキャッチ可能な致命的なエラーをスローします。サービス設定にxml設定を使用してみてください。

service.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" ]

service.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>
0
Rivsen