design-patterns - repositorios - laravel repository i5
¿Son los repositorios de Doctrine2 un buen lugar para guardar mis entidades? (3)
Cuando leo documentos sobre repositorios, a menudo se trabaja con entidades y colecciones, pero de forma "solo lectura".
Nunca hay ejemplos en los que los repositorios tengan métodos como insertUser(User $user)
o updateUser(User $user)
.
Sin embargo, al usar SOA, el servicio no debería funcionar con el administrador de la entidad (¿correcto ?, ¿no?) Así que:
- ¿Debería mi servicio conocer el EntityManager global?
- ¿Debería saber mi servicio solo sobre los repositorios usados (digamos, UserRepository & ArticleRepository)?
De las dos preguntas, otra, ¿debería mi servicio persist()
explícitamente persist()
y flush()
mis entidades?
Bueno, ¿cómo consigues tu repositorio cuando no utilizas el entityManager? Después de todo, las entidades no se guardarán de forma mágica sin una conexión a la base de datos, por lo que su servicio debe conocer de algún modo cualquier tipo de conexión.
No sé acerca de los Servicios SOA, pero a mis ojos no hace ninguna diferencia si usa $_em->getRepository()->save($entity)
o $_em->persist($entity)
. Por otro lado, si usa flush en su repositorio, puede terminar con más consultas de las necesarias ya que su repositorio conoce la lógica de negocios.
Creo que hay una forma de hacer esto "de la manera SOA", pero supongo que no persiste en las entidades dentro del repositorio.
Sí, los repositorios generalmente se usan solo para consultas.
Así es como lo hago. La capa de servicio administra la persistencia. La capa de controlador conoce la capa de servicio, pero no sabe nada sobre cómo persisten los objetos modelo ni de dónde vienen. Lo que le importa a la capa del controlador es pedirle a la capa de servicio que persista y devuelva objetos; no le importa cómo se hace realmente.
La capa de servicio en sí es perfectamente adecuada para conocer la capa de persistencia: gerentes de entidades o documentos, repositorios, etc.
Aquí hay un código para hacerlo más 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);
}
}
Si echas un vistazo al patrón de repositorio http://martinfowler.com/eaaCatalog/repository.html ,
se afirma que los repositorios usan una "interfaz tipo colección".
Más tarde, también se escribe "Los objetos se pueden agregar y eliminar del repositorio, como pueden hacerlo desde una simple colección de objetos".
No estoy diciendo que esto sea una biblia, pero conceptualmente no hay nada de malo en ver un repositorio como una colección que puedes consultar. Pero como es una colección, puede agregar, eliminar, ... De hecho, el ObjectRepository debe implementar Doctrine / Common / Collection :)
Por otro lado, lo más importante es no alterar las lecturas y escrituras, como dice CQS. Quizás sea por eso que no permitieron eso directamente, para evitar abusos y leer / escribir mezcla.
EDITAR: Debería haber hablado sobre el flush
. Esto no debería hacerse en el repositorio en sí, ya que podría romper la coherencia transaccional.
Será mejor que mueva la llamada de flush
a algo que envuelva toda la lógica de transacción comercial (un bus de comando que maneja un comando fe?)