Инъекция Symfony 2 EntityManager в сервис

83

Я создал свою собственную службу, и мне нужно ввести доктрину EntityManager, но я не вижу, что на мой сервис вызывается __construct(), и инъекция не работает.

Вот код и конфиги:

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

}

Вот services.yml в моем пакете

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

Я импортировал этот .yml в config.yml в мое приложение, подобное этому

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

И когда я вызываю службу в контроллере

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

Я получаю объект (но не null), но $this->em в UserService имеет значение null, и, как я уже упоминал, конструктор в UserService никогда не назывался

Еще одна вещь: Controller и UserService находятся в разных пакетах (мне действительно нужно, чтобы организовать проект), но все же: все, что работает, отлично работает, я даже могу позвонить

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

в том же контроллере, который я использую, чтобы получить UserService и получить действительный (не пустой) объект EntityManager.

Похоже, что мне не хватает части конфигурации или некоторой связи между UserService и конфигурацией Doctrine.

  • 0
    Вы пробовали инъекцию сеттера? Оно работает?
  • 0
    Если под «установкой инъекции» вы подразумеваете добавление метода установки для EntityManager в мой сервис и вызов контроллера с параметром $ this-> get ('doctrine.orm.entity_manager') в качестве параметра, то да, я пробовал, и это работает. Но мне действительно нравится использовать правильную инъекцию через конфиг
Показать ещё 2 комментария
Теги:
dependency-injection

4 ответа

101
Лучший ответ

Ваш метод конструктора классов следует называть __construct(), а не __constructor():

public function __construct(EntityManager $entityManager)
{
    $this->em = $entityManager;
}
  • 1
    Привет, в этом примере, как я могу изменить соединение по умолчанию на любое другое?
63

Для современной справки в Symfony 2.4+ вы больше не можете использовать аргументы для метода инжекции конструктора. В соответствии с документацией вы должны пройти:

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

И тогда они будут доступны в том порядке, в котором они были указаны через аргументы (если их больше 1).

public function __construct(EntityManager $entityManager) {
    $this->em = $entityManager;
}
  • 8
    Вы можете сделать: app / console container: debug и узнать, какие сервисы вы также используете.
9

Примечание по состоянию на Symfony 3.3 EntityManager обесценивается. Вместо этого используйте EntityManagerInterface.

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;
        ...
    }
}
  • 0
    На тот случай, если кто-то наткнется на это и запутается: EntityManager определенно не обесценился. Использование интерфейса помогает с автоматическим подключением и рекомендуется, но ни в коем случае не требуется. И интерфейс существует уже давно. Здесь нет ничего нового.
  • 0
    Это ответ. Однако, пожалуйста, сделайте ссылку: stackoverflow.com/questions/22154558/…
Показать ещё 1 комментарий
4

С 2017 года и Symfony 3.3 вы можете зарегистрировать репозиторий как сервис со всеми его преимуществами.

Отметьте мой пост Как использовать репозиторий с Doctrine как услугу в Symfony для более общего описания.


В вашем конкретном случае исходный код с настройкой будет выглядеть так:

1. Используйте в своих службах или контроллере

<?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. Создать новый пользовательский репозиторий

<?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. Регистрация услуг

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

    Test\CommonBundle\:
       resource: ../../Test/CommonBundle

Ещё вопросы

Сообщество Overcoder
Наверх
Меню