3

私の問題は、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 について知る必要があり、関連するエンティティが削除されたときに削除する必要があります。

entityClassBlockにプロパティを追加entityIdし、BlockListener の postLoad イベントで関連エンティティをロードすることを想像しました。しかし、関連するエンティティが存在しない場合はどうなるでしょうか? postLoad でブロックを削除できません。

したがって、関連エンティティの削除を監視する別のリスナーを作成し、そのリスナーで参照ブロックを削除することを想像しました。

しかし、これは、ブロックに入れることができるすべてのエンティティに対してリスナーを追加する必要があることを意味します。

それは機能する可能性がありますが、非常に複雑に思えます...誰かがより良いアイデアを持っているのではないでしょうか?

4

1 に答える 1

0

あなたの質問をよく理解できたかどうかはわかりませんが、エンティティ内にエンティティを持ち、親が削除されたときに子エンティティを削除したい場合は、エンティティをブロックとして扱い、複合パターンを使用することもできます。

基本的に、エンティティとブロックで同じインターフェイスを使用できます。エンティティでは、表示機能は次のようになります。

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

于 2012-06-19T23:26:21.980 に答える