Я знаю, этот вопрос кажется ужасным на первый взгляд.
Часть моей модели хранится в файле * .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, но я не вижу решения.
Как я могу это сделать?
вы можете настроить прослушиватель на prePersist, preUpdate, …, а затем внедрить в него сервис через конфигурацию сервиса
Как правило, хорошей идеей является построение отношений между сущностями, когда они покидают архитектуру 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
}
Что вы должны сделать, это что-то вроде:
public function getStaticObject($staticObjectRepository)
{
return $staticObjectRepository->getById($this->staticObjectId);
}
Конечно, вы также можете найти другие ответы на этот вопрос. Например: Инъекция или доступ к сервисному контейнеру внутри объекта