私の問題は、Doctrine ドキュメントのStrategy Patternの記事で説明されているものとまったく同じです:
- ページ エンティティ
- ページにはいくつかのブロックを含めることができます
- ブロックは、テキスト、画像、フォーム、カレンダーなどである可能性があります... (戦略)
- ページは、含まれているブロックについては知っていますが、その動作については知りません
- ブロック継承は不可
説明されているソリューション (戦略パターン) はまさに私が必要としているものと思われます (詳細については記事を読んでください):
ページ:
<?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 について知る必要があり、関連するエンティティが削除されたときに削除する必要があります。
entityClass
Blockにプロパティを追加entityId
し、BlockListener の postLoad イベントで関連エンティティをロードすることを想像しました。しかし、関連するエンティティが存在しない場合はどうなるでしょうか? postLoad でブロックを削除できません。
したがって、関連エンティティの削除を監視する別のリスナーを作成し、そのリスナーで参照ブロックを削除することを想像しました。
しかし、これは、ブロックに入れることができるすべてのエンティティに対してリスナーを追加する必要があることを意味します。
それは機能する可能性がありますが、非常に複雑に思えます...誰かがより良いアイデアを持っているのではないでしょうか?