Введення Symfony 2 EntityManager в експлуатацію


96

Я створив свій власний сервіс, і мені потрібно внести доктрину 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 config.


Ви пробували ін'єкцію сетера? Це працює?
gremo

Якщо під словом «ін’єкція сеттера» ви маєте на увазі додавання методу сетеру для EntityManager на моєму сервісі та виклик контролера з параметром $ this-> get ('doctrine.orm.entity_manager'), то так, я спробував, і це працює. Але мені дуже подобається використовувати правильну ін'єкцію через конфігурацію
Андрій Заварин,

2
Я маю на увазі це: symfony.com/doc/current/book/ ... у будь-якому випадку __constructorпомилка.
gremo

Гм, ніж я не пробував ін'єкцію сетера __construct вирішив проблему, але в будь-якому випадку дякую за допомогу!
Андрій Заварин

Відповіді:


112

Слід викликати метод конструктора вашого класу __construct(), а не __constructor():

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

2
Привіт, у цьому прикладі, як я можу змінити з'єднання зі стандартного на будь-яке інше?
ptmr.io

Правильно, але було б ще краще, якби ви використовували інтерфейс. public function __construct(EntityManagerInterface $entityManager)
Hugues D

65

Для сучасних посилань, у 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 І дізнатися, якими службами ви також користуєтесь.
Hard Fitness

18

Примітка станом на 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;
        ...
    }
}

1
Про всяк випадок, якщо хтось натрапить на це і розгубиться: EntityManager, безумовно, не амортизується. Використання інтерфейсу допомагає в автоматичному підключенні і рекомендується, але ні в якому разі не потрібно. І інтерфейс існує довгий час. Тут нічого справді нового.
Церад

Це відповідь. Тим НЕ менше, будь ласка , зробіть посилання: stackoverflow.com/questions/22154558 / ...
TFont

Оновлення до власного рішення. Правильним способом тепер має бути використання сутностей та сховищ. Менеджер об'єктів вже природним чином вводиться у сховище. Ви можете побачити приклад тут: youtu.be/AHVtOJDTx0M
Robert Saylor

7

З 2017 року та Symfony 3.3 ви можете зареєструвати сховище як послугу з усіма перевагами.

Перегляньте мій допис Як використовувати сховище з Doctrine as Service у 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.