2

私はデータマッパーパターンにまったく慣れていません。私にとって、最も基本的な例よりも複雑なすべてのもので失敗するので、私は何かが欠けていると思います。

ページで構成された単純なWebサイトがあるとします。

class Page {
    private $id     = null;
    private $parent = null;
    private $title  = null;
    private $body   = null;

    public function setId($id)              { $this->id     = (int) $id; }
    public function setParent(Page $parent) { $this->parent = $parent;   }
    public function setTitle($title)        { $this->title  = $title;    }
    public function setBody($body)          { $this->body   = $body;     }

    public function getId()     { return $this->id;     }
    public function getParent() { return $this->parent; }
    public function getTitle()  { return $this->title;  }
    public function getBody()   { return $this->body;   }
}

次に、ツリーの奥深くにあるページ7をインスタンス化します。

  • ページ1
    • 2ページ
      • 3ページ
        • 4ページ
          • 5ページ
            • 6ページ
              • 7ページ
データマッパーパターンを使用して、次のマッパークラスを使用します。

class PageMapper {
    public function fetch($id) {
        //...
        $data = $db->fetchRow("SELECT * FROM `pages` WHERE `id` = ?", $id);
        $page = new Page();
        $page->setId($data['id']);
        $page->setTitle($data['title']);
        $page->setBody($data['body']);
        if ($data['parent_id'] !== null) {
            $page->setParent(
                $this->fetch($data['parent_id']);
            );
        }
    }

    public function save(Page $page) {
        //...
    }
 }

問題は明らかです。ルートページまですべての親をインスタンス化する必要があります。

ここで、ページがその子について知る必要があると想像してください。つまり、ルートページをインスタンス化する場合は、ツリー全体をロードする必要があります。

解決策は、親/子がオンデマンドでのみロードされることですが、それは、ドメインオブジェクトがマッパーからデータをプルするためにマッパーについて知る必要があることを意味します...そして分離はなくなります。

ドメインモデル(Pageクラスのインスタンス)は、データマッパーレイヤー(分離)について何も知らないはずですが、それでもそれらのタスク(親/子の取得)を実行できます。

これらの条件で関心の分離は達成できますか?はいの場合、どのように?

4

1 に答える 1

1

データマッパーパターンを実装する orm フレームワークである Doctrine を見てください。

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#one-to-many-self-referencing

あなたのアプローチの問題は、ツリー全体(子)のインスタンス化ではなく、使用するクエリの量です。

教義のアプローチを見てください。そこには、1 つのクエリで一度に読み込まれる children プロパティがあります。

また、orm に自作のソリューションを実装することも決してお勧めしません。

考えられる解決策は、クロージャーを使用することです。

class Page {
//...
    public function setParents(Closure $pages)
    {
        $this->parents = $pages;
    } 
}

class PagesMapper {

public function fetch() {
//fetch the page ...
$parents = function($parent) use($id, $db) {
        parents = $db->query(/* select parent... */);
        $pages = array();
        foreach($parents as $parent) {
            $page = new Page(); 
            $page->id = $parent->id;
            //...
            $pages[] = $page;
        }
        return $pages;
    };
    $page->setParents($parents);
    return $page;
}
}

そのため、ページ ドメインには永続化レイヤーに関する知識がありません。

于 2013-03-17T10:01:59.703 に答える