Использование EntityManager внутри объектов Doctrine 2.0
У меня есть 2 объекта: Country (id, name) и Mapping (id, object, internalId, externalId).
Страна и сопоставление не связаны с ассоциациями (поскольку Mapping имеет строки не только для страны). Мне нужно получить внешний идентификатор для страны, используя следующие условия:
-
country.id = mapping.internalId
-
mapping.object = 'country'
Итак, я планирую добавить функцию getExternalId() в стране
function getExternalId() {
$em = Registry::getEntityManager();
$mapping = $em->getRepository('Mapping')->findOneBy(array(
'object' => 'country',
'internalId' => $this->getId()
));
return !empty($mapping) ? $mapping->getExternalId() : false;
}
Вопросы:
- Хорошо ли использовать EntityManager внутри сущностей? Если нет, объясните, как получить внешний идентификатор в моем случае?
- Возможно, можно связать страну и картографию с помощью файлов yaml?
Спасибо заранее!
Ответы
Ответ 1
Не рекомендуется позволять объекту сущности полагаться на диспетчер сущности. Он связывает сущность с уровнем персистентности, что было проблемой, которую специально пыталась решить Doctrine 2. Самая большая проблема, связанная с менеджером сущности, заключается в том, что она делает вашу модель жестко протестированной изолированно от базы данных.
Вероятно, вы должны полагаться на объекты сервиса для обработки операций, которые зависят от менеджера сущностей.
// CountryService
public function getExternalId($country) {}
Кроме того, вы можете создать прокси-методы в своей модели, чтобы вызвать объект службы, который установлен извне. Объект службы будет намного легче издеваться во время тестирования, чем менеджер объектов.
$country->setService($countryService);
$country->getExternalId();
// Country
public function getExternalId()
{
$this->_service->getExternalId($this);
}
Ответ 2
Это может быть не лучшая идея, но есть простой способ сделать это.
Класс 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;
}
}
Если вы создаете новый объект, а не запрашиваете его из базы данных, вам нужно будет установить диспетчер сущностей вручную, например, с помощью метода setter.
Ответ 3
Я думаю, что вам нужно использовать Entity Repositories. Они подробно описаны в документации, хотя найти информацию по ней немного сложно. Вот ссылка на статью " Приступая к работе", в которой описано, как создать "хранилище" функций "доступа" для ваших сущностей.
Кроме того, вот несколько псевдокодов, с которых можно начать:
<?php
// repositories/CountryRepository.php
use Doctrine\ORM\EntityRepository;
class CountryRepository extends EntityRepository
{
public function getExternalId()
{
Ответ 4
Небольшое добавочное дополнение к этому (PHP 5.4 находится в альфа-2 во время этого сообщения), который может быть полезен в будущем:
Вот несколько примеров использования php 5.4 в Doctrine2; один из которых называется активным объектом и обеспечивает активную функциональность стиля записи в Doctrine 2, включая доступ к диспетчеру сущности изнутри объекта.