Доктрина 2: страница, блок, шаблон стратегии и связанная сущность

Моя проблема точно такая же, как описана в Шаблон стратегии в документации 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.

Итак, я решил создать другого слушателя, наблюдающего за удалением связанного объекта, и удалить ссылающийся блок в этом слушателе.

Но это означает, что мне нужно добавить прослушиватель для каждой сущности, которую можно поместить в блок.

Это может сработать, но кажется очень сложным... может быть, у кого-то есть идея получше?


person Lionel Gaillard    schedule 24.04.2012    source источник


Ответы (1)


Я не уверен, правильно ли я понял ваш вопрос, но если вы хотите иметь сущности внутри сущностей и удалять дочерние сущности при удалении отца, вы также можете рассматривать сущность как блок и использовать шаблон Composite.

В основном вы можете использовать один и тот же интерфейс для сущности и блоков, а для сущности функция отображения может выглядеть примерно так:

foreach ($block in $blocks) {
  $block->display();
}

Для удаления всех дочерних элементов при удалении родительского объекта вы можете просто сделать это в деструкторе объекта.

function __destruct() {
   foreach ($block in $blocks) {
     /* call a common interface function that does all that need to be done, implemented on each block */
   }
}

Подробнее о составном шаблоне: http://en.wikipedia.org/wiki/Composite_pattern.

person Álvaro    schedule 19.06.2012