Comment injecter un dépôt dans un service en Symfony?
je dois injecter deux objets dans ImageService
. L'un d'eux est une instance de Repository/ImageRepository
, que j'obtiens comme ceci:
$image_repository = $container->get('doctrine.odm.mongodb')
->getRepository('MycompanyMainBundle:Image');
alors comment puis-je déclarer cela dans mes services.yml? Voici le service:
namespace MycompanyMainBundleServiceImage;
use DoctrineODMMongoDBDocumentRepository;
class ImageManager {
private $manipulator;
private $repository;
public function __construct(ImageManipulatorInterface $manipulator, DocumentRepository $repository) {
$this->manipulator = $manipulator;
$this->repository = $repository;
}
public function findAll() {
return $this->repository->findAll();
}
public function createThumbnail(ImageInterface $image) {
return $this->manipulator->resize($image->source(), 300, 200);
}
}
5 réponses
Voici une solution nettoyée pour ceux qui viennent de Google comme moi:
mise à Jour: ici, c'est le Symfony 2.6 (et plus) solution:
services:
myrepository:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine.orm.entity_manager", getRepository]
arguments:
- MyBundle\Entity\MyClass
myservice:
class: MyBundle\Service\MyService
arguments:
- "@myrepository"
solution dépréciée (Symfony 2,5 et moins):
services:
myrepository:
class: Doctrine\ORM\EntityRepository
factory_service: doctrine.orm.entity_manager
factory_method: getRepository
arguments:
- MyBundle\Entity\MyClass
myservice:
class: MyBundle\Service\MyService
arguments:
- "@myrepository"
j'ai trouvé ce lien et cela a fonctionné pour moi:
parameters:
image_repository.class: Mycompany\MainBundle\Repository\ImageRepository
image_repository.factory_argument: 'MycompanyMainBundle:Image'
image_manager.class: Mycompany\MainBundle\Service\Image\ImageManager
image_manipulator.class: Mycompany\MainBundle\Service\Image\ImageManipulator
services:
image_manager:
class: %image_manager.class%
arguments:
- @image_manipulator
- @image_repository
image_repository:
class: %image_repository.class%
factory_service: doctrine.odm.mongodb
factory_method: getRepository
arguments:
- %image_repository.factory_argument%
image_manipulator:
class: %image_manipulator.class%
dans le cas où si vous ne voulez pas définir chaque dépôt comme un service, à partir de la version 2.4
vous pouvez faire ce qui suit, ( default
est un nom du gestionnaire d'entité):
@=service('doctrine.orm.default_entity_manager').getRepository('MycompanyMainBundle:Image')
2017 et Symfony 3.3+ fait ce beaucoup plus simple.
Vérifier mon post Comment utiliser un Référentiel avec la Doctrine de Service dans Symfony pour une description plus générale.
à votre code, Tout ce que vous devez faire est d'utiliser composition sur héritage - un des modèles solides.
1. Créer son propre dépôt sans dépendance directe sur Doctrine
<?php
namespace MycompanyMainBundle\Repository;
use Doctrine\ORM\EntityManagerInterface;
use MycompanyMainBundle\Entity\Image;
class ImageRepository
{
private $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(Image::class);
}
// add desired methods here
public function findAll()
{
return $this->repository->findAll();
}
}
2. Ajouter enregistrement de configuration avec PSR-4 basé autoregistration
# app/config/services.yml
services:
_defaults:
autowire: true
MycompanyMainBundle\:
resource: ../../src/MycompanyMainBundle
3. Maintenant, vous pouvez ajouter n'importe quelle dépendance n'importe où via constructo injection
use MycompanyMainBundle\Repository\ImageRepository;
class ImageService
{
public function __construct(ImageRepository $imageRepository)
{
$this->imageRepository = $imageRepository;
}
}
dans mon cas se base sur @Tomáš Votruba réponse et cette question je propose les approches suivantes:
Sans Héritage
-
créer une classe D'Adaptateur Générique:
namespace AppBundle\Services; use Doctrine\ORM\EntityManagerInterface; class RepositoryServiceAdapter { private $repository=null; /** * @param EntityManagerInterface the Doctrine entity Manager * @param String $entityName The name of the entity that we will retrieve the repository */ public function __construct(EntityManagerInterface $entityManager,$entityName) { $this->repository=$entityManager->getRepository($entityName) } public function __call($name,$arguments) { if(empty($arrguments)){ //No arguments has been passed $this->repository->$name(); } else { //@todo: figure out how to pass the parameters $this->repository->$name(...$argument); } } }
-
Ensuite chaque entité définir un service, par exemple dans mon cas de définir un (j'utilise php pour définir les services symfony):
$container->register('ellakcy.db.contact_email',AppBundle\Services\Adapters\RepositoryServiceAdapter::class) ->serArguments([new Reference('doctrine'),AppBundle\Entity\ContactEmail::class]);
Avec Héritage
-
même étape 1 mentionnée ci-dessus
-
étendre la classe
RepositoryServiceAdapter
par exemple:namespace AppBundle\Service\Adapters; use Doctrine\ORM\EntityManagerInterface; use AppBundle\Entity\ContactEmail; class ContactEmailRepositoryServiceAdapter extends RepositoryServiceAdapter { public function __construct(EntityManagerInterface $entityManager) { parent::__construct($entityManager,ContactEmail::class); } }
-
service du Registre:
$container->register('ellakcy.db.contact_email',AppBundle\Services\Adapters\RepositoryServiceAdapter::class) ->serArguments([new Reference('doctrine')]);
soit le cas où vous avez une bonne façon testable de fonction teste votre base de données beavior aussi il aide vous sur la moquerie dans le cas où vous voulez tester votre service sans avoir à vous soucier trop sur la façon de le faire. Par exemple, supposons que nous ayons le service suivant:
//Namespace definitions etc etc
class MyDummyService
{
public function __construct(RepositoryServiceAdapter $adapter)
{
//Do stuff
}
}
et le Repoitoryserviceadapter adapte le dépôt suivant:
//Namespace definitions etc etc
class SomeRepository extends \Doctrine\ORM\EntityRepository
{
public function search($params)
{
//Search Logic
}
}
de sorte que vous pouvez facilement moquer / hardcode / émuler le comportement de la méthode search
défini dans SomeRepository
en se moquant soit le RepositoryServiceAdapter
en non-héritage approche ou le ContactEmailRepositoryServiceAdapter
dans l'héritage.