web-dev-qa-db-fra.com

Les référentiels Doctrine2 sont-ils un bon endroit pour sauver mes entités?

Lorsque je lis des documents sur les référentiels, c'est souvent pour travailler avec des entités et des collections mais de manière "en lecture seule".

Il n'y a jamais d'exemples où les référentiels ont des méthodes comme insertUser(User $user) ou updateUser(User $user).

Cependant, lors de l'utilisation de SOA, Service ne devrait pas fonctionner avec Entity Manager (c'est vrai, n'est-ce pas?) Donc:

  1. Mon service doit-il connaître le gestionnaire d'entités global?
  2. Mon service devrait-il uniquement connaître les référentiels utilisés (disons, UserRepository & ArticleRepository)

De ces deux questions, une autre, mon service devrait-il jamais explicitement persist() & flush() mes entités?

53
Trent

Oui, les référentiels sont généralement utilisés uniquement pour les requêtes.

Voici comment je le fais. couche service gère la persistance. La couche contrôleur connaît la couche service, mais ne sait pas comment les objets du modèle sont persistants ni d'où ils viennent. Pour ce qui importe à la couche contrôleur, c'est de demander à la couche service de persister et de renvoyer les objets - peu importe comment cela se fait réellement.

La couche de service elle-même est parfaitement adaptée pour connaître la couche de persistance: gestionnaires d'entités ou de documents, référentiels, etc.

Voici un code pour le rendre plus clair:

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

Si vous jetez un œil au modèle de référentiel http://martinfowler.com/eaaCatalog/repository.html ,

il est précisé que les référentiels utilisent une "interface de type collection".

Plus tard, il est également écrit "Les objets peuvent être ajoutés et supprimés du référentiel, comme ils peuvent l'être à partir d'une simple collection d'objets".

Je ne dis pas que c'est une Bible, mais il n'y a rien de mal sur le plan conceptuel à voir un référentiel comme une collection que vous pouvez interroger. Mais comme c'est une collection, vous pouvez ajouter, supprimer, ... En fait, ObjectRepository devrait implémenter Doctrine\Common\Collection :)

D'un autre côté, le plus important n'est pas de gâcher les lectures et les écritures, comme le dit CQS. C'est peut-être pourquoi ils n'ont pas permis cela directement, pour éviter les abus et le mélange lecture/écriture.

EDIT: J'aurais dû parler de flush. Cela ne doit pas être effectué dans le référentiel lui-même, car cela pourrait rompre la cohérence transactionnelle.

Vous feriez mieux de déplacer l'appel flush vers quelque chose qui enveloppe toute la logique de transaction métier (un bus de commande gérant une commande f.e?)

3
Florian

Eh bien, comment obtenez-vous votre référentiel lorsque vous n'utilisez pas entityManager? Après tout, les entités ne seront pas enregistrées comme par magie sans connexion à la base de données, donc votre service doit en quelque sorte être au courant de tout type de connexion.

Je ne connais pas les services SOA, mais à mes yeux, cela ne fait aucune différence si vous utilisez $_em->getRepository()->save($entity) ou $_em->persist($entity). d'autre part, si vous utilisez le vidage dans votre référentiel, vous risquez de vous retrouver avec bien plus de requêtes que nécessaire, car votre référentiel connaît désormais la logique métier.

Je pense qu'il existe un moyen de faire cela "la SOA façon", mais je suppose que cela ne persiste pas les entités dans le référentiel.

1
Sgoettschkes