96 votes

Symfony 2 EntityManager injection dans le service

J'ai créé mon propre service et j'ai besoin d'injecter la 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 configurations :

<?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 baluchon

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

J'ai importé ce fichier .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);

J'obtiens 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 cela pour garder le projet organisé), mais malgré cela, tout le reste fonctionne bien, je peux même appeler

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

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

On dirait qu'il me manque un élément de configuration ou un lien entre la configuration de UserService et de Doctrine.

112voto

richsage Points 12266

La méthode du constructeur de votre classe doit être appelée __construct() pas __constructor() :

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

65voto

Chadwick Meyer Points 382

Pour une 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 passeriez à l'intérieur :

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

Et ils seraient alors disponibles dans l'ordre où ils ont été listés via les arguments (s'il y en a plus d'un).

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

18voto

Robert Saylor Points 11

Note à partir de Symfony 3.3 EntityManager est déprécié. 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;
        ...
    }
}

7voto

Tomáš Votruba Points 78

Depuis 2017 et Symfony 3.3 vous pouvez enregistrer le référentiel en tant que service avec tous les avantages qu'il présente.

Vérifiez mon poste Comment utiliser le référentiel avec Doctrine comme service dans Symfony ? pour une description plus générale.


Pour votre cas spécifique, le code original avec le tuning ressemblerait à ceci :

1. Utilisation dans vos services ou votre 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X