2013-06-13 7 views
16

Ho una domanda sulle migliori pratiche in Symfony 2. Scusa se è un po 'vago e soggettivo. Immagino di poter riassumere la mia domanda come:Migliori pratiche di symfony. Le query dovrebbero essere in repository o servizi?

"I repository sono sempre il posto giusto per le domande?".

In questo momento sto inserendo la maggior parte delle mie query di dottrine nei repository di entità. La maggior parte delle azioni del mio controller fanno cose tipiche come la query per un'entità o una raccolta di entità, lanciare un'eccezione o un reindirizzamento a seconda del risultato, altrimenti aggiorna una o più entità. La maggior parte delle azioni è più complessa di quanto possa essere fatto in modo efficiente con le query standard -> find, -> findBy etc. La maggior parte richiede join. Quando una query coinvolge più entità, a volte non sono sicuro di quale repository debba entrare. Suppongo che ci sia l'entità root della query ma ... a volte i dati delle entità unite sono più importanti e rilevanti, quindi è sbagliato per inserirlo nel repository dell'entità root.

Funziona bene, ma io tendo a finire con un sacco di domande quasi uguali ma leggermente diverse nei miei repository. Venire con i nomi e tenere traccia esattamente di ciò che ognuno fa può diventare confuso e noioso. La maggior parte di queste query viene utilizzata da solo uno o due azioni del controller (spesso utilizzate raramente) nello stesso controller. Mi sento come se stessi ingombrando i miei repository con roba troppo specializzata e raramente usata.

Sembra che solo le azioni più semplici debbano essere incapsulate in un oggetto o servizio. Quindi, ho iniziato a svolgere molte delle mie query direttamente nel servizio piuttosto che in un repository. È facile guardare l'azione in un unico punto. È una pratica corretta?

+1

il controller dovrebbe essere uno strato molto sottile tra il mondo delle applicazioni e il mondo http e consiglio sempre di mettere le query nei repository. –

risposta

9

Le query devono essere tenuti nella vostra entità repository e non nel vostro controller per poter riutilizzo li facilmente.

Ecco come si presentano i repository. Fornire una posizione riutilizzabile per le query del database.

Ci sono tuttavia alcune situazioni in cui è possibile migliorare tutte le query nel repository ... specialmente quando si tratta di filtrare dove possono essere necessarie molte query.

Benjamin Eberlei (creatore di Doctrine) considera 5 metodi pubblici in una classe per essere ok e 10 per essere abbastanza grande. Di recente ha pubblicato un interessante articolo dal titolo "On Taming Repository Classes in Doctrine" sul suo blog.

In parte mi piace la soluzione trait del repository filtrabile di KnpLabs nel proprio DoctrineBehaviors.

caratteristiche lo rendono il test più difficile, ma si può avere una più pulito e più facile da mantenere repository ... dove si dovrebbe tenere le vostre domande.

+2

Grazie per i link, sono entrambi interessanti. Non avrei intenzione di mettere domande nei miei controller. Sto solo cercando un modo per evitare di gonfiare i miei repository con un sacco di simili ma non proprio le stesse query con nomi simili ma non proprio uguali. – tetranz

9

Si può fare qualcosa in mezzo.

definire un servizio:

blog.post_manager: 
    class: Acme\BlogBundle\Entity\Manager\PostManager 
    arguments: 
     em: "@doctrine.orm.entity_manager" 
     class: Acme\BlogBundle\Entity\Post 

quindi creare la classe Manager:

use Doctrine\ORM\EntityManager; 
use Doctrine\ORM\EntityRepository; 

class PostManager 
{ 
    protected $em; 

    protected $repo; 

    protected $class; 

    public function __construct(EntityManager $em, $class) { 
     $this->em = $em; 
     $this->class = $class; 
     $this->repo = $em->getRepository($class); 
    } 

    public function get($id) 
    { 
     return $this->repo->findById($id); 
    } 
} 

In questo modo, si può ancora lasciare domande a cui appartengono, in repository, consentendo riutilizzo del codice attraverso il servizio di gestione che può essere utilizzato in questo modo in qualsiasi controller:

$this->container->get('blog.post_manager')->get(1); 

Poiché il servizio ice si occupa dell'iniezione della classe e del gestore di entità alla classe Manager, questo mantiene anche il controller più sottile e meglio lo allontana dal modello.

+1

+1 le classi manager sono un buon consiglio anche se la vera domanda era dove mantenere le sue domande - che dovrebbe essere quasi sempre il repository. Una classe manager offre il vantaggio di astrarre diversi modi per accedere al database. puoi avere una classe manager utilizzando un repository di entità, un'altra utilizzando un repository di documenti un'altra utilizzando un back-end di storage completamente diverso. finché tutti implementano la stessa interfaccia, è possibile scambiarli nel controller. Questo è il modo in cui FOSUserBundle gestisce doctrine orm, odm e propel :) – nifr

+1

"In questo modo, puoi ancora lasciare le domande a cui appartengono, nei repository, [...]" –

+0

ah è nascosto lì, scusa è stata la lettura veloce :) – nifr

Problemi correlati