Подтвердить что ты не робот

Использование 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?

Спасибо заранее!

4b9b3361

Ответ 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, включая доступ к диспетчеру сущности изнутри объекта.