Использование EntityManager внутри сущностей Doctrine 2.0

У меня есть 2 объекта: Страна (id, имя) и Mapping (id, объект, internalId, externalId). Country и Mapping не связаны ассоциациями (поскольку в Mapping есть строки не только для страны). Мне нужно получить внешний идентификатор для страны, используя следующие условия:

  • country.id = mapping.internalId
  • mapping.object = 'country'

Поэтому я планирую добавить функцию getExternalId() в Country.

function getExternalId() {
    $em = Registry::getEntityManager();

    $mapping = $em->getRepository('Mapping')->findOneBy(array(
        'object'     => 'country',
        'internalId' => $this->getId()
    ));

    return !empty($mapping) ? $mapping->getExternalId() : false;
}

Вопросы:

  1. Является ли хорошей практикой использование EntityManager внутри сущностей? Если нет, объясните, как получить внешний идентификатор в моем случае?
  2. Может быть, можно связать Country и Mapping с помощью файлов yaml?

Заранее спасибо!


person Torchello    schedule 05.11.2010    source источник


Ответы (4)


Не рекомендуется разрешать сущностному объекту полагаться на диспетчер сущностей. Он привязывает сущность к уровню персистентности, что было проблемой, которую Doctrine 2 специально пыталась решить. Самая большая проблема, связанная с использованием диспетчера сущностей, заключается в том, что он затрудняет тестирование вашей модели изолированно, вдали от базы данных.

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

// CountryService
public function getExternalId($country) {}

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

$country->setService($countryService);
$country->getExternalId();

// Country
public function getExternalId()
{
   $this->_service->getExternalId($this);
}  
person Bryan M.    schedule 05.11.2010
comment
Я ищу хорошие учебники по реализации службы для доктрины. Может кто знает хорошие учебники. - person user257980; 06.04.2011
comment
Должен ли сервисный объект в этом случае быть внутренним по отношению к объекту или вы можете использовать его вне объекта? Например. $service = новая Страна\ServiceObject; $ExtId = $service->getExternalId($country); - person calumbrodie; 24.06.2011

Это может быть не лучшая идея, но есть простой способ сделать это.

Класс UnitOfWork в доктрине будет гидратировать любую сущность, реализующую ObjectManagerAware, с помощью менеджера сущностей и метаданных класса для этой сущности.

Все, что вам нужно сделать, чтобы получить менеджер сущностей в вашей сущности, это реализовать интерфейс, как показано в примере ниже:

use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\Persistence\ObjectManagerAware;

/**
 * @ORM\Entity
 */
class MyEntity implements ObjectManagerAware
{
    public function injectObjectManager(ObjectManager $objectManager, ClassMetadata $classMetadata)
    {
        $this->em = $objectManager;
    }
}

Если вы создаете новую сущность, а не запрашиваете ее из базы данных, вам нужно будет установить диспетчер сущностей вручную, например, с помощью метода установки.

person juanmf    schedule 15.07.2014

Я думаю, что вам нужно использовать репозитории сущностей. Они подробно описаны в документации, хотя найти информацию о них немного сложно. Вот ссылка на Начало работы, в которой описано, как можно создать "репозиторий" функций "доступа" для ваших сущностей.

Кроме того, вот некоторый псевдокод для начала:

<?php
// repositories/CountryRepository.php

use Doctrine\ORM\EntityRepository;

class CountryRepository extends EntityRepository
{
    public function getExternalId()
    {
person MikeMurko    schedule 18.10.2011
comment
похоже ссылка мертвая - person Gigala; 11.06.2013
comment
На данный момент ссылка рабочая. Я думаю, что это очень хорошее решение вопроса ОП. - person Nicolás Ozimica; 15.11.2013

Немного передовое дополнение к этому (PHP 5.4 находится в альфа-версии 2 на момент написания этого поста), которое может быть полезно в будущем:

Вот приведены несколько примеров использования трейтов php 5.4 в Doctrine2; один из которых называется активной сущностью и обеспечивает функциональность активного стиля записи в Doctrine 2, включая доступ к диспетчеру сущностей изнутри сущности.

person Fost    schedule 31.10.2011