3
votes

I have an application that consists of a service layer and a repository layer. For both the services and the repositories I have declared interface and I inject the interface for services in the controller and services get injected with interfaces of the repositories. This is all done with autowire set to true.

When I call a method on one of the injected services it all works fine, as long as I don't call a function that needs one of the injected repositories. When I try to call a function that uses one of the repositories I get the following error:

Cannot autowire service "AppBundle\Repository\TestRepository": argument "$em" of method "Doctrine\ORM\EntityRepository::__construct()" must have a type-hint or be given a value explicitly.

Now I figured that this has to do with the fact that this has to to with EntityRepository class from which my repositories extend, cause when I look at the constructor it looks like this:

class TestRepository extends EntityRepository implements TestRepositoryInterface
{
public function __construct(
            EntityManager $em,
            Mapping\ClassMetadata $class
        ) {
            parent::__construct($em, $class);
        }

    /**
     * @return string
     */
    public function getTest(): string
    {
        return 'This is a test';
    }
}

Which clearly contains the $em parameter that is mentioned in the error message. I have just no clue how to solve this. Currently my services and repositories are configured the same in the services.yml, but since the services seem to work, I would think that is not the problem. Do I need to disable autowire for my repositories and configure them manually in the services.yml, or am I just missing something really obvious?

2

2 Answers

7
votes

Repositories cannot be directly instantiated. You need to use EntityManager::getRepository

So you will need to define your repos in services.yml

// services.yml
AppBundle\Repository\UserRepository:
    factory: 'doctrine.orm.entity_manager:getRepository'
    arguments: ['AppBundle\Entity\User']

And then autowire injection should work.

I'll be curious to see if autowire really does catch on. It is inherently frustrating since some services are wired as if by magic while others require manual intervention which could result in a bit of a mess.

2
votes

Actually, there is a way to do that but I'm not sure if we can/should do that or not

class TestRepository extends EntityRepository
{

    // Constructor for autowiring
    public function __construct(EntityManager $em)
    {
        parent::__construct($em, $em->getClassMetadata(Test::class));
    }