Моя проблема точно такая же, как описана в Шаблон стратегии в документации Doctrine :
- Сущность страницы
- Страница может иметь несколько блоков
- Блок может быть текстом, изображением, формой, календарем, ... (стратегия)
- Страница знает о содержащихся в ней блоках, но не знает об их поведении.
- Наследование блоков невозможно
Описанное решение (шаблон стратегии) кажется именно тем, что мне нужно (прочитайте статью для получения дополнительной информации):
Страница:
<?php
namespace Page\Entity;
class Page
{
/**
* @var int
* @Id @GeneratedValue
* @Column(type="integer")
*/
protected $id;
/**
* @var string
* @Column
*/
protected $title;
/**
* @var string
* @Column(type="text")
*/
protected $body;
/**
* @var Collection
* @OneToMany(targetEntity="Block", mappedBy="page")
*/
protected $blocks;
// ...
}
Блокировать:
<?php
namespace Page\Entity;
class Block
{
/**
* @Id @GeneratedValue
* @Column(type="integer")
*/
protected $id;
/**
* @ManyToOne(targetEntity="Page", inversedBy="blocks")
*/
protected $page;
/**
* @Column
*/
protected $strategyClass;
/**
* Strategy object is instancied on postLoad by the BlockListener
*
* @var BlockStrategyInterface
*/
protected $strategyInstance;
// ...
}
Интерфейс стратегии:
<?php
namespace Page\BlockStrategy;
interface BlockStrategyInterface
{
public function setView($view);
public function getView();
public function setBlock(Block $block);
public function getBlock();
public function renderFrontend();
public function renderBackend();
}
Я легко могу представить, какой была бы моя стратегия, если бы я отображал форму или календарь; но что, если моя стратегия заключается в отображении содержимого другого объекта?
Блок должен знать о классе/идентификаторе объекта и должен быть удален при удалении связанного объекта.
Я предполагал добавить свойства entityClass
и entityId
в Block и загрузить связанный объект в событии postLoad в BlockListener. Но что, если связанная сущность не существует? Я не могу удалить блок в postLoad.
Итак, я решил создать другого слушателя, наблюдающего за удалением связанного объекта, и удалить ссылающийся блок в этом слушателе.
Но это означает, что мне нужно добавить прослушиватель для каждой сущности, которую можно поместить в блок.
Это может сработать, но кажется очень сложным... может быть, у кого-то есть идея получше?