web-dev-qa-db-fra.com

Injection Symfony 2 EntityManager en service

J'ai créé mon propre service et je dois injecter doctrine EntityManager, mais je ne vois pas que __construct()] est appelé sur mon service et l'injection ne fonctionne pas. .

Voici le code et les configs:

<?php

namespace Test\CommonBundle\Services;
use Doctrine\ORM\EntityManager;

class UserService {

    /**
     *
     * @var EntityManager 
     */
    protected $em;

    public function __constructor(EntityManager $entityManager)
    {
        var_dump($entityManager);
        exit(); // I've never saw it happen, looks like constructor never called
        $this->em = $entityManager;
    }

    public function getUser($userId){
       var_dump($this->em ); // outputs null  
    }

}

Voici services.yml dans mon paquet

services:
  test.common.userservice:
    class:  Test\CommonBundle\Services\UserService
    arguments: 
        entityManager: "@doctrine.orm.entity_manager"

J'ai importé ce .yml dans config.yml dans mon application comme ça

imports:
    # a few lines skipped, not relevant here, i think
    - { resource: "@TestCommonBundle/Resources/config/services.yml" }

Et quand j'appelle le service dans le contrôleur

    $userservice = $this->get('test.common.userservice');
    $userservice->getUser(123);

Je reçois un objet (non nul), mais $this->em dans UserService est null et, comme je l’ai déjà mentionné, le constructeur de UserService n’a jamais été appelé.

Une dernière chose, Controller et UserService sont dans des bundles différents (j'ai vraiment besoin de ça pour garder le projet organisé), mais quand même: tout le reste fonctionne bien, je peux même appeler

$this->get('doctrine.orm.entity_manager')

dans le même contrôleur que j'utilise pour obtenir UserService et obtenir un objet EntityManager valide (non nul).

Apparemment, il me manque un élément de configuration ou un lien entre UserService et Doctrine config.

95
Andrey Zavarin

La méthode de constructeur de votre classe doit s'appeler __construct(), pas __constructor():

public function __construct(EntityManager $entityManager)
{
    $this->em = $entityManager;
}
112
richsage

Pour référence moderne, dans Symfony 2.4+, vous ne pouvez plus nommer les arguments de la méthode Constructor Injection. Selon le documentation Vous transmettriez:

services:
    test.common.userservice:
        class:  Test\CommonBundle\Services\UserService
        arguments: [ "@doctrine.orm.entity_manager" ]

Et ensuite, ils seraient disponibles dans l'ordre dans lequel ils ont été listés via les arguments (s'il y en a plus que 1).

public function __construct(EntityManager $entityManager) {
    $this->em = $entityManager;
}
64
Chadwick Meyer

Remarque à partir de Symfony 3.3, EntityManager est amorti. Utilisez EntityManagerInterface à la place.

namespace AppBundle\Service;

use Doctrine\ORM\EntityManagerInterface;

class Someclass {
    protected $em;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->em = $entityManager;
    }

    public function somefunction() {
        $em = $this->em;
        ...
    }
}
16
Robert Saylor

Depuis 2017 et Symfony 3.3 , vous pouvez enregistrer le référentiel en tant que service , avec ses avantages il a.

Vérifiez mon message Comment utiliser le référentiel avec Doctrine en tant que service dans Symfony pour des informations plus générales la description.


Pour votre cas spécifique, le code d'origine avec réglage ressemblerait à ceci:

1. Utilisez dans vos services ou contrôleur

<?php

namespace Test\CommonBundle\Services;

use Doctrine\ORM\EntityManagerInterface;

class UserService
{
    private $userRepository;

    // use custom repository over direct use of EntityManager
    // see step 2
    public function __constructor(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function getUser($userId)
    {
        return $this->userRepository->find($userId);
    }
}

2. Créer un nouveau référentiel personnalisé

<?php

namespace Test\CommonBundle\Repository;

use Doctrine\ORM\EntityManagerInterface;

class UserRepository
{
    private $repository;

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

    public function find($userId)
    {
        return  $this->repository->find($userId);
    }
}

3. Enregistrer les services

# app/config/services.yml
services:
    _defaults:
        autowire: true

    Test\CommonBundle\:
       resource: ../../Test/CommonBundle
7
Tomáš Votruba