I'm learning Symfony and I've been trying to create a service, using a repository. I've created my repositories and entities from generate:entity, so they should be fine.
So far what I got in my services.yml is:
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%
But when I try to call the service, I get this error:
Catchable Fatal Error: Argument 2 passed to Doctrine\ORM\EntityRepository::__construct() must be an instance of Doctrine\ORM\Mapping\ClassMetadata, none given, called in
Then I tried to create the service just using an entity. My services.yml would look like:
services:
myservice:
class: %mytest.class%
factory-service: doctrine.orm.default_entity_manager
factory-method: getRepository
arguments:
- %mytest.entity%
But for this, I get:
Error: Call to undefined method
Test\TestBundle\Entity\Brand::findAll
Does anybody know what am I doing wrong?
Thanks
Here is how we did it in KnpRadBundle: https://github.com/KnpLabs/KnpRadBundle/blob/develop/DependencyInjection/Definition/DoctrineRepositoryFactory.php#L9
Finally it should be:
my_service:
class: Doctrine\Common\Persistence\ObjectRepository
factory_service: doctrine # this is an instance of Registry
factory_method: getRepository
arguments: [ %mytest.entity% ]
UPDATE
Since 2.4, doctrine allows to override the default repositor factory.
Here is a possible way to implement it in symfony: https://gist.github.com/docteurklein/9778800
DEPRECATION WARNING: No more factory_service
and factory_method
. This is how you should do it since Symfony 2.6 (for Symfony 3.3+ check below):
parameters:
entity.my_entity: "AppBundle:MyEntity"
services:
my_entity_repository:
class: AppBundle\Repository\MyEntityRepository
factory: ["@doctrine", getRepository]
arguments:
- %entity.my_entity%
The new setFactory() method was introduced in Symfony 2.6. Refer to older versions for the syntax for factories prior to 2.6.
http://symfony.com/doc/2.7/service_container/factories.html
EDIT: Looks like they keep changing this, so since Symfony 3.3 there's a new syntax:
# app/config/services.yml
services:
# ...
AppBundle\Email\NewsletterManager:
# call the static method
factory: ['AppBundle\Email\NewsletterManagerStaticFactory', createNewsletterManager]
Check it out: http://symfony.com/doc/3.3/service_container/factories.html
You may have used the wrong YAML-Keys. Your first configuration works fine for me using
- factory_service instead of factory-service
- factory_method instead of factory-method
Since 2017 and Symfony 3.3+ this is now much easier.
Note: Try to avoid generic commands like generate:entity
. They are desined for begginers to make project work fast. They tend to bare bad practises and take very long time to change.
Check my post How to use Repository with Doctrine as Service in Symfony for more general description.
To your code:
1. Update your config registration to use PSR-4 based autoregistration
# app/config/services.yml
services:
_defaults:
autowire: true
Test\TestBundle\:
resource: ../../src/Test/TestBundle
2. Composition over Inheritance - Create own repository without direct dependency on 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 in any Service or Controller via constructor injection
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();
// ...
}
}
I convert service.yml to service.xml, and update DependencyInjection Extension, everything is working for me. I don't know why, but yml config will thrown Catchable Fatal Error. You can try using xml config for service config.
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>
Symfony 3.3 and doctrine-bundle 1.8 there is a Doctrine\Bundle\DoctrineBundle\Repository\ContainerRepositoryFactory which helps to create repository as service.
Example
What we want
$rep = $kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository(Brand::class);
ORM description
# Brand.orm.yaml
...
repositoryClass: App\Repository\BrandRepository
...
Service description
# 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'
sf 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%
来源:https://stackoverflow.com/questions/17228417/symfony-2-creating-a-service-from-a-repository