Symfony2 entityManager в модели

Я собираюсь использовать entity_manager в своей модели. Но entity_manager доступен только в контроллере: throw $em = $this->get('doctrine.orm.entity_manager'). Итак, я должен определить методы модели с параметром $em. Это затрудняет тестирование phpUnit и нарушает структуру приложения. Например:

class Settings
{
    public static function getParam( $em, $key )
    {
        $em->createQuery("
            SELECT s
            FROM FrontendBundle:Settings s
            WHERE s.param = {$key}
        ");
        return $em->getResult();
    }
}

Есть ли какой-либо подход к использованию службы entity_manager в разделе модели?

Ответ 1

Во-первых, начальная нота: по соглашению ваш класс Entity должен, вероятно, быть единственным. Итак, настройка, а не настройки. Вы можете утверждать, что "настройки" как группы связанных настроек можно рассматривать как одну сущность. Тем не менее, что-то иметь в виду.

В Doctrine2 вы должны использовать репозиторий для создания этого типа запроса. В коде, где вы собираетесь называть Settings::getParam, вы должны выбрать репозиторий и запросить его. В symfony2, скажем:

// $em is your entitymanager, as you were going to pass to your method above
// $key is the key you were going to pass to your method above
$repository = $em->getRepository('\FrontendBundle\Settings');
$setting = $repository->getByParam($key);

По умолчанию без написания кода репозитории определяют getByXXXX для каждого поля в вашей организации.

Если у вас есть более сложный запрос, вы можете расширить репозиторий.

use Doctrine\ORM\EntityRepository;

class SettingsRepository extends EntityRepository 
{
    public function getBySomeComplicatedQuery() {
        $sort_order = $this->getEntityManager()
            ->createQuery('SELECT count(s) FROM FrontendBundle\Settings s WHERE s.value > 32')
            ->getResult(Query::HYDRATE_SINGLE_SCALAR);
    }

}

И тогда вы вызовете этот метод таким же образом.

Другие будут выступать за использование объекта Manager, который тогда не будет привязан к Entity/ORM, но в этом случае я считаю ненужным осложнение.

Doctrine2 специально разработан, чтобы не позволить вам использовать запросы в вашем файле Entity; Сущности и EntityManager фактически являются двумя аспектами стандартного слоя модели, раздробленными для применения лучших практик. См. Эту статью: http://symfony2basics.jkw.co.nz/get-symfony2-working/entities/

Ответ 2

Запросы в классе Entity

Постановка запросов в вас сущность кажется мне странной. Точно так же, как размещение запросов в вашем классе модели в Доктрине 1, это не считается хорошей практикой. Классы объектов должны быть легкими.

Я действительно изучаю Doctrine2 и думал о подобной проблеме: где поставить запросы?

В Доктрине 1 есть специальные классы таблиц, и я ожидал чего-то подобного в Доктрине 2.

Шаблон хранилища

Сегодня я узнал, что Doctrine 2 использует шаблон репозитория: http://www.doctrine-project.org/docs/orm/2.0/en/reference/working-with-objects.html#custom-repositories

Однако для извлечения экземпляра класса репозитория вам необходимо использовать Entity Manager. Так или иначе вам это нужно.

Тем не менее, выбор шаблона репозитория представляется лучшим выбором.

На мой взгляд, если вы настаиваете на том, чтобы метод запроса в вашем классе Entity должен был передать ему диспетчер сущностей.

Тестирование

Почему необходимость управления диспетчером сущностей затрудняет тестирование? По моему опыту явные зависимости упрощают тестирование, так как вы можете контролировать их в тесте (и имитировать их, например).

С другой стороны, передача диспетчера сущностей по каждому методу не является правильным выбором. В таком случае я сделаю зависимость зависимой и добавлю ее в конструктор.