2014-05-07 16 views
5

Attualmente sto usando una funzione per ottenere i miei repository in questo modo:Utilizzando un esterno repository di un controller in Symfony2

public function getRepositories() 
{ 
    // Tasks 
    $tasks = $this->getDoctrine() 
     ->getRepository('Model:Task'); 

    // Task Info 
    $taskInfos = $this->getDoctrine() 
     ->getRepository('Model:TaskInfo'); 


    return array(
     'tasks'    => $tasks, 
     'taskInfos'   => $taskInfos, 
    ); 
} 

Così nelle mie azioni di controllo, posso solo chiamare alcuni SQL come questo:

Ma ora che ho alcuni controller, ho notato che sto copiando la stessa funzione getRepositories() in ognuno di essi che non è buono in quanto replica ripetutamente il codice.

Quello che voglio è avere come una classe di supporto, e questa potrebbe essere una delle funzioni in questo.

Ma come faccio a farlo, dato che la classe helper non sarà un controller e lì per $this->getDoctrine() ovviamente non funzionerebbe?

Grazie

risposta

6

È possibile utilizzare i servizi (http://symfony.com/doc/current/book/service_container.html) e iniettare dottrina.

services: 
    my.helper.class: 
     class: Acme\MyBundle\Helper\MyHelper 
     arguments: [ @doctrine.orm.entity_manager ] 

<?php 

namespace Acme\MyBundle\Helper; 

use Doctrine\ORM\EntityManager; 

class MyHelper 
{ 
    protected $manager; 

    public function __construct(EntityManager $manager) 
    { 
     $this->manager = $manager; 
    } 

    public function getRepositories() 
    { 
     $tasks = $this->manager->getRepository('Model:Task'); 
     $taskInfos = $this->manager->getRepository('Model:TaskInfo'); 

     return array(tasks, taskInfos); 
    } 
} 

Detto questo, io non capisco lo scopo di questo nella vostra situazione come controller hanno lo scopo di ottenere i dati e restituirlo.

Non si sta duplicando la logica.

Sembra troppo, il gestore di entità è già un aiuto in questo modo.

+0

Sei una leggenda !! Grazie è esattamente quello di cui avevo bisogno !! – b85411

+0

Sono felice di poter essere utile! – LBridge

3

In realtà non si guadagna nulla con il codice che si desidera scrivere. Una pratica migliore sarebbe quella di creare una classe di repository per ogni entità, che ha iniettato il gestore di entità. È inoltre possibile definire un altro servizio di repository astratto che tali servizi di entità si estenderanno. Lo faccio in questo modo nelle mie applicazioni e l'ho trovato davvero utile, perché posso aggiungere le proprie funzioni al repository che sto usando.

posso fare qualcosa di simile nel controllore:

$this->getTaskRepository->findOneById(1); 
$this->getTaskRepository->getSomeTasks(); // executes a query with query builder 
2

@ suggerimento di Tobias funziona bene, ma si dovrebbe anche prendere in considerazione una buona pratice che dice: "Iniettare solo i servizi che hanno bisogno di".

Il punto qui è che si sta iniettando il Ente Gestore per ottenere due repository Doctrine (tasks & tasksInfos), tenere a mente che il Ente Gestore ha fatto di più che solo recuperare Dottrina Repositories.

Quando è necessario un repository di dottrine all'interno del proprio helper, si inserisce di solito un gestore di entità e quindi si recupera il repository. Tuttavia, non stai iniettando il servizio di cui hai bisogno, stai iniettando un gestore che ti aiuta a ottenere ciò di cui hai bisogno.

altro vincolo (si può considerare) è che un repository Doctrine possono essere recuperati solo attraverso un gestore di entità, in modo da non fare ha alcun controllo sulla sua costruzione.

Così, l'unico modo per iniettare i repository invece che a seconda del gestore di entità è quello di considerare using Factory services and methodsdelegare la creazione di servizi e quindi iniettare i servizi competenti.

Vorrei quindi suggerire,

namespace Acme\MyBundle\Helper; 

// Add the relevant use(s) here ... 

class AnyGivenService 
{ 
    protected $taskRepository; 
    protected $taskInfoRepository; 

    public function __construct(TaskRepository $taskRepository, TaskInfoRepository $taskInfoRepository) 
    { 
     $this->taskRepository = $taskRepository; 
     $this->taskInfoRepository= $taskInfoRepository; 
    } 

    public function doSomethingWithYourRepositories() 
    { 
     // .... 
    } 
} 

Mentre definizione del servizio dovrebbe assomiglia,

<service id="any_given_service" class="AnyGivenService"> 
    <argument type="task_repository" /> 
    <argument type="task_info_repository" /> 
</service> 

<service id="task_repository" class="TaskRepository" factory-service="doctrine.orm.entity_manager" factory method="getRepository"> 
    <argument>Task</argument> 
</service> 

<service id="task_info_repository" class="TaskInfoRepository" factory-service="doctrine.orm.entity_manager" factory method="getRepository"> 
    <argument>TaskInfo</argument> 
</service> 

I vantaggi,

  • Il codice è pulito e più leggibile come il costruttore di te il tuo servizio è più specifico sulle sue reali esigenze.
  • Testability, invece di creare un mock sia per il gestore delle entità che per i repository, devi solo prendere in giro i tuoi repository.
Problemi correlati