Как внедрить контейнер / сервис в сущность Doctrine2 в Symfony2?

Я знаю, этот вопрос кажется ужасным на первый взгляд.

Вот что у меня есть:

Часть моей модели хранится в файле * .yaml и загружается, когда это необходимо. Давайте назовем это StaticObject. Он имеет около 10 объектов, не масштабируется по дизайну и доступен только для чтения. Каждый StaticObject имеет собственный идентификатор, и я могу получить объект с данным идентификатором из службы в контейнере, например:

$container->get('static_object_repository')->getById('foo');

Теперь у меня есть объект, который имеет «связь» с этим StaticObject. Я хочу, чтобы он сохранялся в базе данных как ID, поэтому я добавил новое поле $ staticObjectId к сущности, например:

class MyEntity
{
//...

/**
* @ORM\Column(type="string", name="static_object_id")
*/
protected $staticObjectId;

//...
}

Теперь каждый раз, когда я хочу получить StaticObject от объекта, я вызываю сервис из моего контейнера, например:

$staticObject = $container->get('static_object_repository')->getById($entity->getStaticObjectId());

и когда я хочу изменить этот связанный объект, я делаю что-то вроде:

$entity->setStaticObjectId($staticObject->getId());

Я надеюсь, что вы получили достаточно информации о моем коде. Скажи мне, если я пропущу что-то важное для тебя, чтобы понять проблему.

Это то, что я хочу:

Я хочу хранить экземпляр StaticObject непосредственно в объекте, поэтому я могу просто получить и установить его. Просто

$entity->getStaticObject();
//and
$entity->setStaticObject($staticObject);

Моей первой мыслью было скрыть все необходимые преобразования в методах получения и установки. Итак, я получаю:

class MyEntity
{
//...

public function setStaticObject(StaticObject $so)
{
$this->staticObjectId = $so->getId();
}

public function getStaticObject()
{
return $container->get('static_object_repository')->getById($this->staticObjectId);
}

//...
}

Но подождите … У меня не может быть контейнера в моей модели. Не так ли? Я нигде не могу найти, как внедрить контейнер / сервис в сущность.

Моя вторая мысль состояла в том, чтобы использовать пользовательский тип отображения Doctrine. И снова — вы не можете внедрить в него службу (поскольку пользовательский тип является классом, а объект / служба отсутствует). я сделал все из этого раздела документации Doctine2 а также я прочитал этот раздел в кулинарной книге Symfony2, но я не вижу решения.

Как я могу это сделать?

1

Решение

вы можете настроить прослушиватель на prePersist, preUpdate, …, а затем внедрить в него сервис через конфигурацию сервиса

документы потрясающие

2

Другие решения

Как правило, хорошей идеей является построение отношений между сущностями, когда они покидают архитектуру ORM и не достигают уровня повседневных приложений. Лучший способ сделать это — сохранить сущность простой:

class MyEntity
{
public function setStaticObject(StaticObject $so)
{
$this->staticObject = $so;
}

public function getStaticObject()
{
return $this->staticObject;
}
}

и используйте пользовательский Hydrator для установки StaticObject сразу после загрузки строки:

https://www.techpunch.co.uk/development/create-custom-doctrine2-hydrator-symfony2

Если ленивая загрузка важна, то это не большой шаг, чтобы использовать собственный Hydration для внедрения класса StaticObjectFactory, который вы можете использовать следующим образом:

// MyEntity
public function getStaticObject()
{
if (!isset($this->staticObject)) {
$this->staticObject = $this->staticObjectFactory->loadById($this->getStaticObjectId());
}

return $this->staticObject
}
2

Что вы должны сделать, это что-то вроде:

public function getStaticObject($staticObjectRepository)
{
return $staticObjectRepository->getById($this->staticObjectId);
}

Конечно, вы также можете найти другие ответы на этот вопрос. Например: Инъекция или доступ к сервисному контейнеру внутри объекта

0