web-dev-qa-db-ja.com

Doctrine2リポジトリは私のエンティティを保存するのに良い場所ですか?

リポジトリに関するドキュメントを読むとき、エンティティとコレクションを操作することはよくありますが、「読み取り専用」の方法です。

リポジトリがinsertUser(User $user)updateUser(User $user)のようなメソッドを持つ例は決してありません。

ただし、SOAを使用する場合、ServiceはEntity Managerと連携してはいけません(そうですね)。

  1. 私のサービスはグローバルEntityManagerを認識する必要がありますか?
  2. 私のサービスが使用されているリポジトリのみを知っている必要があります(たとえば、UserRepositoryとArticleRepository)

その両方の質問から、別の質問として、私のサービスは明示的にpersist()flush()私のエンティティである必要がありますか?

53
Trent

はい、リポジトリは通常、クエリにのみ使用されます。

これが私のやり方です。 サービス層 は永続性を管理します。コントローラレイヤはサービスレイヤを認識していますが、モデルオブジェクトがどのように永続化されているのか、またどこから来ているのかは認識していません。コントローラー層が気にするのは、サービス層にオブジェクトを永続化して返すように要求することです。実際にどのように行われるかは関係ありません。

サービス層自体は、永続層(エンティティまたはドキュメントマネージャー、リポジトリなど)について知るのに最適です。

わかりやすくするためのコードを次に示します。

class UserController
{
    public function indexAction()
    {
        $users = $this->get('user.service')->findAll();
        // ...
    }

    public function createAction()
    {
        // ...
        $user = new User();
        // fill the user object here
        $this->get('user.service')->create($user);
        // ...
    }
}

class UserService
{
    const ENTITY_NAME = 'UserBundle:User';

    private $em;

    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }

    public function findAll()
    {
        return $this->em->getRepository(self::ENTITY_NAME)->findAll();
    }

    public function create(User $user)
    {
        // possibly validation here

        $this->em->persist($user);
        $this->em->flush($user);
    }
}
41

リポジトリパターンを見てみると http://martinfowler.com/eaaCatalog/repository.html

リポジトリは「コレクションのようなインターフェース」を使用すると述べられています。

後で、「オブジェクトの単純なコレクションからできるように、オブジェクトをリポジトリに追加したり、リポジトリから削除したりできる」とも書かれています。

これが聖書だと言っているのではありませんが、概念的には、クエリを実行できるコレクションのようなリポジトリを表示することに問題はありません。しかし、それはコレクションなので、追加、削除などができます...実際、ObjectRepositoryはDoctrine\Common\Collectionを実装する必要があります:)

一方、CQSが言うように、最も重要なのは読み取りと書き込みを台無しにしないことです。だからこそ、悪用や読み取り/書き込みの混在を避けるために、それを直接許可しなかったのかもしれません。

編集:flushについて話すべきだった。これは、トランザクションの一貫性を損なう可能性があるため、リポジトリ自体でしないでください

flush呼び出しを、ビジネストランザクションロジック全体をラップするもの(コマンドf.e?を処理するコマンドバス)に移動することをお勧めします。

3
Florian

まあ、entityManagerを使用していないときにリポジトリを取得するにはどうすればよいですか?結局のところ、エンティティはデータベースへの接続なしでは魔法のように保存されないので、サービスはなんらかの種類の接続を何らかの方法で認識している必要があります。

SOAサービスについては知りませんが、$_em->getRepository()->save($entity)または$_em->persist($entity)を使用しても、私の目にはまったく違いはありません。一方、リポジトリでフラッシュを使用すると、リポジトリでビジネスロジックが認識されるようになるため、クエリが必要以上に多くなる可能性があります。

「SOA方法」」を実行する方法はあると思いますが、リポジトリ内のエンティティを永続化していないと思います。

1
Sgoettschkes