2011-02-01 7 views
7

Ho recentemente approfondito l'uso di un ORM nella mia applicazione CodeIgniter e uno che ho scelto è Propel. Ora questo mi dà il potere di utilizzare fondamentalmente le classi Propels come il 'Modello', ma è questa cattiva practive?Utilizzo di classi ORM direttamente dal controller in MVC, cattive abitudini?

Quindi il mio codice del controller potrebbe essere il seguente:

<?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);  
     } 
    } 
?> 

Voglio risolvere questo problema prima di continuare a sviluppare la mia domanda. Un esempio di come dovrei fare questo sarebbe molto utile se si considera che questa è una cattiva pratica per favore.

Grazie in anticipo

+0

Ricorda che la peggiore "cattiva pratica" è il lago di consistenza, ma sì, in realtà. :-) –

+0

Verifica: http://stackoverflow.com/questions/4568553/mvc-in-php-fat-model-or-fat-controller e http://www.survivethedeepend.com/zendframeworkbook/en/1.0/ il modello dovrebbe essere una lettura interessante per te. –

risposta

7

Sì, è una cattiva pratica.

Il modello deve contenere tutta la logica dei dati e astrarre tutto dal resto del programma. Per il resto dell'applicazione, i modelli dovrebbero apparire come scatole nere da cui ricava i suoi dati. Se si utilizza un ORM come modello, si è leaking the abstraction e si accoppia strettamente il controller al livello dati.

Invece, crea i tuoi modelli e gestisci l'ORM lì. In questo modo se hai bisogno di aggiustare il tuo modello di dati, puoi semplicemente cambiarlo in un punto (il livello del modello) e sapere che l'astrazione terrà.

0

Ho trovato che questo è un male necessario occasionale quando il tuo ORM sta seguendo il modello Active Row.

Il problema che si verifica sempre è che un modello rappresenta solo una singola istanza della struttura dati. Non ha senso aggiungere metodi di recupero della raccolta nel modello.

Qui è dove ho storicamente utilizzato un livello di servizio per gestire l'estrazione nelle raccolte di modelli. Anche se per essere onesti ultimamente ho semplicemente scritto un oggetto helper del controller che astragga solo il mio oggetto tabella.

+0

Oltre al [Record attivo] (http://propelorm.org/reference/active-record.html), Propel ha anche le [classi di query attive] (http://propelorm.org/reference/model-criteria .html) che si occupa di collezioni di modelli –

4

Con le classi Query utilizzate da Propel, penso che la differenza con un modello più "formale" diventi sempre più piccola. Se questa diventerà una libreria rilasciata nel mondo, sarebbe un vantaggio avere un livello di astrazione in modo da poter avere backend diversi, ma se si tratta di un'applicazione interna userò semplicemente le classi Query come modello.

Ma ricorda che le classi Query sono create per essere percepite come un oggetto reale e che nascondono la parte relazionale quanto più possono. Puoi usare questo a tuo vantaggio. Controlla this article about rewriting your SQL queries with Query methods, in particolare la terza risposta: spostati sempre di più nella tua classe Query, quindi il tuo controller non ha l'impressione di utilizzare un database.

// 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

Dipende molto da quello che stai facendo e perché. in questo esempio stai inserendo una clausola limite nella query: è quella logica di business o di visualizzazione? Dal mio punto di vista, è difficile sostenere che è la logica del business - che torno indietro di 10 elementi è irrilevante per il modello - è solo il modo in cui penso abbia senso usare in una pagina. Se si desidera che la regola sia coerente tra i controller, è possibile impostare un valore di configurazione per applicare la coerenza. Ma metterlo nel modello rende il modello inutilmente grande (c'è una differenza tra modelli di grasso e modelli obesi)

Direi che i limiti, gli ordini e gli offset non sono spesso logiche di business. Anche un semplice dove potrebbe o non potrebbe essere a seconda del caso.Se c'è un join lì, è un segno che qualcosa non va.

L'esempio di Jan Fabry è in gran parte piuttosto buono. filterByTitle ha lo stesso aspetto di titleContainsWord. filterByPublishedAt (array ('max' => time())) è molto peggio di -> published(). In generale, meno controller devono sapere sulla struttura interna dei dati, meglio è.