2014-05-07 9 views
5

Obecnie używam funkcji, aby moje repozytoria tak:Korzystanie z repozytorium poza kontrolerem w 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, 
    ); 
} 

Więc moje działania kontrolera, mogę tylko nazwać jakąś SQL takiego:

$repositories = $this->getRepositories(); 
$task = $repositories['tasks']->findOneById($id); 

Ale teraz, gdy mam kilka kontrolerów, zauważyłem, że kopiuję tę samą funkcję getRepositories() do każdego, co nie jest dobre, ponieważ wielokrotnie replikuje kod.

Czego chcę, to mieć klasę pomocników, a to może być jedna z funkcji w tym.

Ale jak to zrobić, biorąc pod uwagę, że klasa pomocnika nie będzie kontrolerem, a tam dla $this->getDoctrine() oczywiście nie będzie działać?

Dzięki

Odpowiedz

6

Można używać usług (http://symfony.com/doc/current/book/service_container.html) i wstrzyknąć doktryny.

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

Powiedział, że ja naprawdę nie rozumiem cel ten w sytuacji jak kontrolery mają uzyskać dane i odesłać go.

Nie powielacie logiki.

Wydaje się, że za dużo, podmiot zarządzający jest już w ten sposób pomocnikiem.

+0

Jesteś legendą !! Dzięki, właśnie tego potrzebowałem !! – b85411

+0

Cieszę się, że mogę być pomocny! – LBridge

3

Naprawdę nic nie zyskujesz za pomocą kodu, który chcesz napisać. Lepszą praktyką byłoby utworzenie klasy repozytorium dla każdej jednostki, do której został dodany menedżer encji. Można również zdefiniować inną usługę abstrakcyjnego repozytorium, którą będą rozszerzać te usługi encji. Robię to w ten sposób w moich aplikacjach i uznałem, że jest to bardzo przydatne, ponieważ mogę dodawać własne funkcje do repozytorium, którego używam.

mogę zrobić coś takiego w kontrolerze:

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

@ sugestia Tobias działa dobrze, ale należy również rozważyć dobrą Practice, który mówi: „wstrzyknąć tylko usługi trzeba”.

Chodzi o to, że jesteś wstrzykiwanie Entity Menedżer dostać dwa repozytoriów Doktryna (tasks & tasksInfos), należy pamiętać, że The Podmiot Menedżer zrobił więcej niż tylko pobierać Doktryna Repozytoriami.

Gdy potrzebujesz repozytorium doktryny w swoim pomocniku, zwykle wstrzyknąłbyś menedżer encji, a następnie odzyskałeś swoje repozytorium. Jednak nie wstrzykujesz potrzebnej Ci usługi, wstrzykujesz menedżerowi , który pomaga uzyskać to, czego potrzebujesz.

Innym ograniczeniem (jeden może rozważyć) jest to, że repozytorium Doktryna mogą być pobierane tylko za pośrednictwem podmiotu Menedżer, więc robimy nie mają żadnej kontroli nad jego budowy.

Tak, to jedyny sposób, aby wprowadzić swoje repozytoria zamiast w zależności od podmiotu Manager to rozważyć using Factory services and methodsdelegować tworzenie usług, a następnie wstrzyknąć odpowiednich usług.

bym wtedy sugerować,

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() 
    { 
     // .... 
    } 
} 

Podczas definicja usług powinny wygląda,

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

Zalety,

  • Twój kod jest czysty i bardziej czytelne jako Konstruktor Twojej usługi jest bardziej konkretny o swoich rzeczywistych potrzebach.
  • Testowalność Zamiast kpić z menedżera encji i repozytoriów, wystarczy sfałszować repozytoria.
Powiązane problemy