ti-enxame.com

Os repositórios do Doctrine2 são um bom local para salvar minhas entidades?

Quando leio documentos sobre repositórios, geralmente é para trabalhar com entidades e coleções, mas de maneira "somente leitura".

Nunca há exemplos em que os repositórios tenham métodos como insertUser(User $user) ou updateUser(User $user).

No entanto, ao usar SOA, o Serviço não deve estar funcionando com o Entity Manager (isso mesmo, não é?), Portanto:

  1. Meu serviço deve estar ciente do EntityManager global?
  2. Meu serviço deve conhecer apenas os repositórios usados ​​(digamos, UserRepository & ArticleRepository)

A partir dessas duas perguntas, outra, meu serviço deve sempre explicitamente persist() & flush() minhas entidades?

53
Trent

Sim, os repositórios geralmente são usados ​​apenas para consultas.

Aqui está como eu faço isso. O camada de serviço gerencia a persistência. A camada do controlador conhece a camada de serviço, mas não sabe nada sobre como os objetos de modelo são persistidos nem de onde eles vêm. O que a camada do controlador se importa é pedir para a camada de serviço persistir e retornar objetos - não importa como é realmente feito.

A própria camada de serviço é perfeitamente adequada para saber sobre a camada de persistência: gerenciadores de entidades ou documentos, repositórios, etc.

Aqui está um código para torná-lo mais claro:

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
Elnur Abdurrakhimov

Se você der uma olhada no padrão do repositório http://martinfowler.com/eaaCatalog/repository.html ,

afirma-se que os repositórios usam uma "interface semelhante a coleção".

Posteriormente, também está escrito "Os objetos podem ser adicionados e removidos do Repositório, assim como em uma simples coleção de objetos".

Não estou dizendo que essa é uma Bíblia, mas conceitualmente não há nada errado em ver um repositório como uma coleção que você pode consultar. Mas como é uma coleção, você pode adicionar, remover ... Na verdade, o ObjectRepository deve implementar Doctrine\Common\Collection :)

Por outro lado, o mais importante é não mexer nas leituras e gravações, como diz o CQS. Talvez seja por isso que eles não permitiram isso diretamente, para evitar abusos e mix de leitura/gravação.

EDIT: Eu deveria ter falado sobre flush. Isso não deve ser feito no próprio repositório, pois pode quebrar a consistência transacional.

É melhor mover a chamada flush para algo que envolva toda a lógica de transação comercial (um barramento de comando manipulando um comando f.e?)

3
Florian

Bem, como você obtém seu repositório quando não está usando o entityManager? Afinal, as entidades não serão salvas magicamente sem uma conexão com o banco de dados; portanto, seu serviço deve estar atento a qualquer tipo de conexão.

Eu não sei sobre os serviços SOA, mas, aos meus olhos, não faz diferença se você usar $_em->getRepository()->save($entity) ou $_em->persist($entity). No Por outro lado, se você usar o flush em seu repositório, poderá ter muito mais consultas do que o necessário, pois seu repositório agora está ciente da lógica de negócios.

Eu acho que existe uma maneira de fazer isso "da maneira SOA"), mas acho que não persiste as entidades no repositório.

1
Sgoettschkes