我的问题正是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();
}
我可以轻易地想象出,如果我要显示一个表格或者一个日历的话,我的策略会是什么;但是如果我的策略是展示另一个实体的内容呢?
这个块需要知道实体类和ID的相关信息,并且在关联的实体被删除时也需要将其删除。
我想到了在 Block 中添加 entityClass
和 entityId
属性,并在 BlockListener 中的 postLoad 事件中加载相关实体。但是如果关联实体不存在呢?我不能在 postLoad 中删除该块。
所以,我想创建另一个监听器来监视相关实体的删除,并在该监听器中删除引用的块。
但这意味着我需要为每个可能放在块中的实体添加一个监听器。
这可能可行,但似乎非常复杂...也许有人有更好的想法吗?