web-dev-qa-db-fra.com

Symfony 3.3 injectant des référentiels dans des services

J'ai un paquet qui se trouve dans un référentiel privé Satis car ses entités et ses référentiels sont partagés entre plusieurs applications.

Le reste des applications qui utilisent cet ensemble sont les applications Symfony 2.7 et 2.8. Je travaille sur une nouvelle application et l'exigence est d'utiliser Symfony 3.3.

Dans l’application symfony 3.3, j’ai essayé ceci dans mon service.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}'

Ce qui précède donne l'exception suivante:

Impossible d'autowire le service "UvmsApiV1Bundle\Service\DealerService": l'argument "$ repository" de la méthode "__construct ()" fait référence à la classe "CbmLtd\UvmsBundle\Repository\DealerRepository" mais ce service n'existe pas. Il ne peut pas être enregistré automatiquement car il provient d'un espace de noms racine différent.

Ok, je suppose que je dois déclarer explicitement ce référentiel en tant que service. Je ne trouve rien dans la documentation de Symfony 3.3 sur la déclaration d'un référentiel en tant que service, et la syntaxe 2.8 ne fonctionne pas non plus.

J'ai ajouté ceci à mon 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

Mais je reçois toujours cette exception:

Impossible d'autowire le service "UvmsApiV1Bundle\Service\DealerService": l'argument "$ repository" de la méthode "__construct ()" fait référence à la classe "CbmLtd\UvmsBundle\Repository\DealerRepository" mais ce service n'existe pas. Il ne peut pas être enregistré automatiquement car il provient d'un espace de noms racine différent.

Je ne peux apporter aucune modification à CbmLtd\UvmsBundle car celui-ci est utilisé par plusieurs applications. Toute aide serait appréciée. J'ai littéralement passé des heures là-dessus, c'est très frustrant.

4
ThePHPUnicorn

J'ai pu le faire en utilisant le fichier services.yml suivant:

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}'

J'ai dû changer légèrement de contrôleur mais ça fonctionne maintenant.

5
ThePHPUnicorn

2018+ et Symfony 3.3+ answer

Vous pouvez aller encore plus loin et utiliser Repositories as Services .

De cette façon, vous utiliserez le câblage automatique de Symfony et sa configuration facile dans la configuration des services.

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. Référentiel

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);
    }
}
1
Tomáš Votruba