Mientras creaba una aplicación en Laravel 4 después de leer el libro de T.Otwell sobre buenos patrones de diseño en Laravel, me encontré creando repositorios para cada tabla de la aplicación.
Terminé con la siguiente estructura de tabla:
- Estudiantes: id, nombre
- Cursos: id, nombre, teacher_id
- Profesores: id, nombre
- Asignaciones: id, nombre, course_id
- Puntajes (actúa como un pivote entre los estudiantes y las tareas): student_id, task_id, scores
Tengo clases de repositorio con métodos de búsqueda, creación, actualización y eliminación para todas estas tablas. Cada repositorio tiene un modelo Eloquent que interactúa con la base de datos. Las relaciones se definen en el modelo según la documentación de Laravel: http://laravel.com/docs/eloquent#relationships .
Al crear un nuevo curso, todo lo que hago es llamar al método create en el repositorio de cursos. Ese curso tiene asignaciones, por lo que al crear una, también quiero crear una entrada en la tabla de puntuación para cada alumno del curso. Hago esto a través del Repositorio de asignaciones. Esto implica que el repositorio de tareas se comunica con dos modelos Eloquent, con el modelo Assignment y Student.
Mi pregunta es: como esta aplicación probablemente crecerá en tamaño y se introducirán más relaciones, ¿es una buena práctica comunicarse con diferentes modelos de Eloquent en repositorios o debería hacerlo usando otros repositorios en su lugar (me refiero a llamar a otros repositorios desde el repositorio de asignaciones ) ¿O debería hacerse en los modelos Eloquent todos juntos?
Además, ¿es una buena práctica usar la tabla de puntajes como un pivote entre las tareas y los estudiantes o debería hacerse en otro lugar?
$a = $this->account->getById(1)
no puedo simplemente encadenar métodos como$a->getActiveUsers()
. Bien, podría usar$a->users->...
, pero luego estoy devolviendo una colección Eloquent y ningún objeto stdClass y estoy vinculado a Eloquent nuevamente. ¿Cuál es la solución a esto? Declarar otro método en el repositorio de usuarios como$user->getActiveUsersByAccount($a->id);
? Me encantaría saber cómo resuelves esto ...Estoy terminando un gran proyecto usando Laravel 4 y tuve que responder todas las preguntas que me está haciendo en este momento. Después de leer todos los libros de Laravel disponibles en Leanpub y toneladas de Google, se me ocurrió la siguiente estructura.
Digamos que estoy construyendo una base de datos de películas. Tendría al menos las siguientes clases de Eloquent Model:
Una clase de repositorio encapsularía cada clase de Eloquent Model y sería responsable de las operaciones CRUD en la base de datos. Las clases del repositorio podrían verse así:
Cada clase de repositorio ampliaría una clase BaseRepository que implementa la siguiente interfaz:
Una clase de servicio se utiliza para unir varios repositorios y contiene la "lógica empresarial" real de la aplicación. Los controladores solo se comunican con las clases de servicio para las acciones de creación, actualización y eliminación.
Entonces, cuando quiero crear un nuevo registro de película en la base de datos, mi clase MovieController puede tener los siguientes métodos:
Depende de usted determinar cómo envía los datos a sus controladores, pero digamos que los datos devueltos por Input :: all () en el método postCreate () se ven así:
Dado que MovieRepository no debería saber cómo crear registros de Actor, Director o Studio en la base de datos, usaremos nuestra clase MovieService, que podría verse así:
Así que lo que nos queda es una separación de preocupaciones agradable y sensata. Los repositorios solo conocen el modelo Eloquent que insertan y recuperan de la base de datos. Los controladores no se preocupan por los repositorios, simplemente entregan los datos que recopilan del usuario y los pasan al servicio apropiado. Al servicio no le importa cómo se guardan los datos que recibe en la base de datos, simplemente entrega los datos relevantes que le dio el controlador a los repositorios apropiados.
fuente
$studio->movies()->associate($movie);
).Me gusta pensar en ello en términos de lo que hace mi código y de lo que es responsable, en lugar de "correcto o incorrecto". Así es como separo mis responsabilidades:
Con esto en mente, siempre tiene sentido usar un repositorio (si crea interfaces, etc. es un tema completamente diferente). Me gusta este enfoque, porque significa que sé exactamente a dónde ir cuando necesito hacer cierto trabajo.
También tiendo a construir un repositorio base, generalmente una clase abstracta que define los valores predeterminados principales, básicamente operaciones CRUD, y luego cada niño puede simplemente extender y agregar métodos según sea necesario, o sobrecargar los valores predeterminados. Inyectar su modelo también ayuda a que este patrón sea bastante robusto.
fuente
Piense en los repositorios como un archivador consistente de sus datos (no solo sus ORM). La idea es que desee capturar datos en una API consistente y fácil de usar.
Si se encuentra haciendo Model :: all (), Model :: find (), Model :: create (), probablemente no se beneficiará mucho de abstraer un repositorio. Por otro lado, si desea aplicar un poco más de lógica empresarial a sus consultas o acciones, es posible que desee crear un repositorio para facilitar el uso de la API para tratar los datos.
Creo que estabas preguntando si un repositorio sería la mejor manera de lidiar con algunas de las sintaxis más detalladas necesarias para conectar modelos relacionados. Dependiendo de la situación, hay algunas cosas que puedo hacer:
Al colgar un nuevo modelo secundario de un modelo principal (uno-uno o uno-muchos), agregaría un método al repositorio secundario
createWithParent($attributes, $parentModelInstance)
y esto simplemente agregaría el$parentModelInstance->id
en elparent_id
campo de los atributos y llamaría a crear.Adjuntando una relación de muchos-muchos, en realidad creo funciones en los modelos para poder ejecutar $ instance-> attachChild ($ childInstance). Tenga en cuenta que esto requiere elementos existentes en ambos lados.
Al crear modelos relacionados en una sola ejecución, creo algo que llamo Gateway (puede estar un poco alejado de las definiciones de Fowler). Manera en que puedo llamar $ gateway-> createParentAndChild ($ parentAttributes, $ childAttributes) en lugar de un montón de lógica que puede cambiar o que complicaría la lógica que tengo en un controlador o comando.
fuente