Symfony 3.3 injecting repositories into services
Asked Answered
L

4

5

I have a bundle which is held in a private Satis repository as its entities and repositories are shared between multiple application.

The rest of the applications that consume that bundle are Symfony 2.7 and 2.8 applications. I'm working on a new application and the requirement is to use Symfony 3.3.

In the symfony 3.3 application I have tried this in my services.yml:

# Learn more about services, parameters and containers at
# http://symfony.com/doc/current/service_container.html
parameters:
    #parameter_name: value

services:
# default configuration for services in *this* file
    _defaults:
        autowire: true
        autoconfigure: true
        # this means you cannot fetch services directly from the container via $container->get()
        # if you need to do this, you can override this setting on individual services
        public: false

    # makes classes in src/AppBundle available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    CbmLtd\UvmsBundle\:
        resource: '../../vendor/cbmltd/uvms-bundle/*'
        exclude: '../../vendor/cbmltd/uvms-bundle/{Entity,Repository}'

    UvmsApiV1Bundle\:
        resource: '../../src/UvmsApiV1Bundle/*'
        exclude: '../../src/UvmsApiV1Bundle/{Entity,Repository}'

The above gives the following exception:

Cannot autowire service "UvmsApiV1Bundle\Service\DealerService": argument "$repository" of method "__construct()" references class "CbmLtd\UvmsBundle\Repository\DealerRepository" but no such service exists. It cannot be auto-registered because it is from a different root namespace.

Ok, so I guess I need to explicitly declare this repository as a service. I cannot find anything in Symfony 3.3 documentation about declaring a repository as a service, and the 2.8 syntax doesn't work either.

I added this to my services.yml:

services:
    ...
    CbmLtd\UvmsBundle\DealerRepository:
        class: CbmLtd\UvmsBundle\Entity\DealerRepository
        factory_service: doctrine.orm.entity_manager
        factory_method: getRepository
        arguments:
            - CbmLtd\UvmsBundle\Entity\Dealer

But I still get this exception:

Cannot autowire service "UvmsApiV1Bundle\Service\DealerService": argument "$repository" of method "__construct()" references class "CbmLtd\UvmsBundle\Repository\DealerRepository" but no such service exists. It cannot be auto-registered because it is from a different root namespace.

I cannot make any changes to CbmLtd\UvmsBundle as this is used by multiple applications. Any help would be appreciated. I've literally spent hours on this, it's very frustrating.

Lw answered 2/7, 2017 at 10:3 Comment(0)
L
5

I was able to do this using the following services.yml:

services:
# default configuration for services in *this* file
    _defaults:
        autowire: true
        autoconfigure: true

    # this means you cannot fetch services directly from the container via $container->get()
    # if you need to do this, you can override this setting on individual services
    public: false

    # makes classes in src/AppBundle available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    CbmLtd\UvmsBundle\:
        resource: '../../vendor/cbmltd/uvms-bundle/*'
        exclude: '../../vendor/cbmltd/uvms-bundle/{Entity,Repository}'

    CbmLtd\UvmsBundle\Repository\DealerRepository:
        factory: doctrine.orm.entity_manager:getRepository
        arguments:
            - CbmLtd\UvmsBundle\Entity\Dealer

    UvmsApiV1Bundle\:
        resource: '../../src/UvmsApiV1Bundle/*'
        exclude: '../../src/UvmsApiV1Bundle/{Entity,Repository}'

I had to change my controller slightly but it's working now.

Lw answered 2/7, 2017 at 10:25 Comment(0)
L
1

2018+ and Symfony 3.3+ answer

You can take this even further and use Repositories as Services.

That way you'll make use of Symfony's autowiring and easy configuration in services config.

1. Services

services:
    _defaults:
        autowire: true
        autoconfigure: true

    CbmLtd\UvmsBundle\:
        resource: '../../vendor/cbmltd/uvms-bundle/*'
        exclude: '../../vendor/cbmltd/uvms-bundle/{Entity}'

    UvmsApiV1Bundle\:
        resource: '../../src/UvmsApiV1Bundle/*'
        exclude: '../../src/UvmsApiV1Bundle/{Entity}'

2. Repository

namespace CbmLtd\UvmsBundle\Repository\DealerRepository;

final class DealerRepository
{
    /**
     * @var Doctrine\ORM\EntityRepository
     */
    private $repository;

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

    public function find($id)
    {
        return $this->repository->find($id);
    }
}
Leigh answered 18/5, 2018 at 19:52 Comment(0)
C
-1

try to change your repository service declaration

your_bundle.your_entity_repository:
    class: Doctrine\ORM\EntityRepository
    factory: ['@doctrine.orm.default_entity_manager', getRepository]
    arguments:
        - YourBundle\Entity\YourEntity

and then inject the repo by referencing it like this:

your_bundle.your_service:
    class: YourBundle\Service\YourService
    arguments:
        - "@your_bundle.your_entity_repository"
    calls:
        - [setContainer, ['@service_container']]
Coworker answered 2/7, 2017 at 10:41 Comment(1)
Got: "Please add the class to service "car_base.app.partnership_repository" even if it is constructed by a factory since we might need to add method calls based on compile-time checks. (3.4)Mccandless
Z
-1

You have a typo in your service declaration, you forgot the "repository" namespace. Also, is the class located in "Entity" or in "Repository"? The service id should be the same as the actual fully-qualified class name. In services.yml, Try:

CbmLtd\UvmsBundle\Repository\DealerRepository:
    class: CbmLtd\UvmsBundle\Repository\DealerRepository

Instead of:

CbmLtd\UvmsBundle\DealerRepository:
    class: CbmLtd\UvmsBundle\Entity\DealerRepository
Zendavesta answered 14/7, 2017 at 10:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.