Dariux
Dariux

Reputation: 4253

How to configure dependency injection for repository class in symfony 3

Symfony generator generated the following class of repository:

namespace AppBundle\Repository;
use AppBundle\Entity\GroupEntity;

/**
 * GroupEntityRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class GroupEntityRepository extends \Doctrine\ORM\EntityRepository
{


}

services.yml:

group_entity_repository:
         class: AppBundle\Repository\GroupEntityRepository
         arguments: ["@doctrine.orm.entity_manager", AppBundle\Entity\GroupEntity]

I configured services.yml wrongly, but I do not now what to use as second argument. So I get the error:

Catchable Fatal Error: Argument 2 passed to Doctrine\ORM\EntityRepository::__construct() must be an instance of Doctrine\ORM\Mapping\ClassMetadata, string given, called in E:\other\dropbox\Dropbox\programavimas\kodo pavyzdziai\htdocs\users_admin_demo\var\cache\dev\appDevDebugProjectContainer.php on line 1626 and defined

How to fix it? I cannot see in the documentation, it just showed the code for generator and final generated class but no services config.

Upvotes: 8

Views: 13477

Answers (3)

Fabien Salles
Fabien Salles

Reputation: 1201

Since Symfony 3.4 you can avoid factory and use a TagRepository service that extends ServiceEntityRepository class instead of directly EntityRepository.

use AppBundle\Entity\GroupEntity;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;

class GroupEntityRepository extends ServiceEntityRepository
{
    public function __construct(RegistryInterface $registry)
    {
        parent::__construct($registry, GroupEntity::class);
    }
}

With this method, your service would be automatically registered with autowiring feature.

You can also do better in all Symfony version by using composition over inheritance.

final class GroupEntityRepository
{
    /** @var EntityManagerInterface */
    private $entityManager;

    /** @var ObjectRepository */
    private $objectRepository;

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

This service can also be autowiring. You can go further by respecting the SOLID principle and create an interface. There is a good explanation in this article (Repository Pattern in Symfony)

Upvotes: 7

Darius.V
Darius.V

Reputation: 938

Example SF 3.4 how to make in xml:

<service id="vop.sales.payment.entity_repository.billing_status"
                 class="Vop\Sales\PaymentBundle\Entity\BillingStatusRepository">
            <factory service="doctrine.orm.entity_manager" method="getRepository"/>
            <argument>Vop\Sales\PaymentBundle\Entity\BillingStatus</argument>
        </service>

Upvotes: 0

Tobias Xy
Tobias Xy

Reputation: 2069

Recommended as of Symfony 3.3:

As of Symfony 3.3 it is recommended to use the actual class name as service id (read this and this).

AppBundle\Repository\GroupEntityRepository:
    factory: 'Doctrine\ORM\EntityManagerInterface:getRepository'
    arguments:
        - AppBundle\Entity\GroupEntity

Original answer:

You can configure your repository service like this:

group_entity_repository:
    class: AppBundle\Repository\GroupEntityRepository
    factory: ["@doctrine.orm.entity_manager", getRepository]
    arguments:
        - AppBundle\Entity\GroupEntity

You will probably never want to invoke the repository constructor yourself. Therefore this approach just uses the entity_manager to get the repository. The service container bascially uses this code to get the repository:

$container->get('doctrine.orm.entity_manager')->getRepository('AppBundle\Entity\GroupEntity');

Upvotes: 20

Related Questions