2011-02-01 6 views
7

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?Usar clases ORM directamente desde el controlador en MVC, ¿mala práctica?

Así que mi código del controlador sería la 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 que llevo en el desarrollo de mi solicitud. Un ejemplo de cómo debería hacer esto sería muy útil si consideras que es una mala práctica, por favor.

Gracias de antemano

+0

Recuerda que la peor "mala práctica" es el lago de la coherencia, pero sí lo es en realidad. :-) –

+0

Comprobar: http://stackoverflow.com/questions/4568553/mvc-in-php-fat-model-or-fat-controller y http://www.survivethedeepend.com/zendframeworkbook/en/1.0/ the.model debería ser interesante para ti. –

Respuesta

7

Sí, es una mala práctica.

El modelo debe contener toda su lógica de datos y abstraerlo todo 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, es leaking the abstraction y acopla firmemente su controlador a su capa de datos.

En lugar de eso, crea tus modelos y trata 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.

0

He encontrado que este es un mal necesario ocasional cuando tu ORM sigue el patrón Active Row.

El problema que siempre 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.

+0

Además de [Active Record] (http://propelorm.org/reference/active-record.html), Propel también tiene las [clases Active Query] (http://propelorm.org/reference/model-criteria .html) que trata de colecciones de modelos –

4

Con las clases Query que Propel ahora usa, 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, simplemente usaría las clases Query como tu modelo.

Pero recuerde que las clases 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 this article about rewriting your SQL queries with Query methods, especialmente la tercera respuesta: vaya más y más a su clase Query, por lo que su controlador no tiene ganas de usar 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(); 
0

Depende mucho de lo que está 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 los modelos gordos y los obesos)

Diría que los límites, los pedidos y las compensaciones a menudo no son de lógica comercial. 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 deben saber los controladores sobre la estructura interna de datos, mejor.

Cuestiones relacionadas