vista mvc modelo explicacion ejemplo descargar curso controlador codigo php orm doctrine propel

modelo - html mvc php



Usar clases ORM directamente desde el controlador en MVC, ¿mala práctica? (4)

He encontrado que esto es un mal necesario ocasional cuando su ORM sigue el patrón de Fila activa .

El problema con el que siempre me encuentro es que un modelo solo representa una sola instancia de la estructura de datos. No tiene sentido agregar métodos de recuperación de colecciones en el modelo.

Aquí es donde históricamente he usado una capa de servicio para manejar colecciones de modelos. Aunque para ser sincero últimamente, simplemente escribí un objeto de ayudante de controlador que simplemente abstrae el objeto de mi tabla.

Recientemente he profundizado en el uso de un ORM en mi aplicación CodeIgniter y he ido a Propel. Ahora bien, esto me da el poder de usar básicamente las clases de Propels como el ''Modelo'' pero ¿es esta mala práctica?

Entonces mi código de controlador sería el siguiente:

<?php class Page extends Controller { function __construct() { parent::__construct(); } function index() { $foo = FooQuery::create()->limit(10)->find(); $data[''content''] = array(''foo''=>$foo); $this->load->view(''home'', $foo); } } ?>

Quiero resolver este problema antes de seguir desarrollando mi aplicación. Un ejemplo de cómo debería hacer esto sería muy útil si consideras que es una mala práctica, por favor.

Gracias por adelantado


Sí, es una mala práctica.

El modelo debe contener toda su lógica de datos y abstraerlo del resto del programa. Para el resto de la aplicación, los modelos deben verse como cajas negras de las cuales obtiene sus datos. Si usa un ORM como su modelo, está filtrando la abstracción y conectando estrechamente su controlador a su capa de datos.

En cambio, crea tus modelos y trata con el ORM allí. De esa manera, si alguna vez necesita ajustar su modelo de datos, puede simplemente cambiarlo en un lugar (la capa de modelo) y saber que se mantendrá la abstracción.


Con las clases de Query ahora usa Propel, creo que la diferencia con un Modelo más "formal" se vuelve cada vez más pequeña. Si esto se convierte en una biblioteca que lanzas al mundo, sería una ventaja tener una capa de abstracción para que puedas tener diferentes backends, pero si es una aplicación interna, solo usaría las clases de Query como tu Modelo.

Pero recuerde que las clases de Query se crean para sentirse como un objeto real, y que ocultan la parte relacional todo lo que pueden. Puedes usar esto a tu favor. Consulte este artículo sobre la reescritura de sus consultas SQL con los métodos de Query , especialmente la tercera respuesta: vaya cada vez más a su clase de Query , por lo que su controlador no tiene la sensación de que utiliza una base de datos.

// Instead of this code in your controller, // tightly coupled to your database logic $books = BookQuery::create() ->filterByTitle(''%war%'') ->filterByPrice(array(''max'' => 10) ->filterByPublishedAt(array(''max'' => time())) ->leftJoin(''Book.Author'') ->where(''Author.Name > ?'', $fameTreshold); // You would use this code in your controller // and create small methods with the business logic in the BookQuery class $books = BookQuery::create() ->titleContainsWord(''war'') ->cheap() ->published() ->writtenByFamousAuthors();


Depende mucho de lo que estás haciendo y por qué. en este ejemplo, usted está poniendo una cláusula de límite en la consulta: ¿es esa lógica de negocio o de pantalla? Desde mi punto de vista, es difícil argumentar que la lógica de negocios -que recupere 10 elementos es irrelevante para el modelo- es solo la cantidad que creo que tiene sentido usar en una página. Si desea que la regla sea coherente en todos los controladores, puede establecer algún valor de configuración para aplicar consistencia. Pero ponerlo en el modelo solo hace que el modelo sea innecesariamente grande (hay una diferencia entre modelos gordos y modelos obesos)

Diría que los límites, las órdenes y las compensaciones a menudo no son lógicas comerciales. Incluso un simple donde podría o no ser dependiendo del caso. Si hay una unión allí, es una señal de que algo está mal.

El ejemplo de Jan Fabry es bastante bueno. filterByTitle me parece lo mismo que titleContainsWord. filterByPublishedAt (array (''max'' => time ())) es mucho peor que -> published (). En general, cuanto menos que los controladores necesiten saber sobre la estructura interna de datos, mejor.