2014-05-07 63 views
5

使用控制器的存儲庫之外我目前使用的功能,讓我的倉庫,像這樣:在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, 
    ); 
} 

所以在我的控制器動作,我可以叫一些這樣的SQL:

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

但是現在我有了幾個控制器,我注意到我正在將相同的getRepositories()函數複製到每個函數中,因爲它不斷重複代碼。

我想要的是有一個助手類,這可能是其中的一個功能。

但我該怎麼做,鑑於助手類不會是一個控制器,並且$this->getDoctrine()顯然不工作?

感謝

回答

6

您可以使用服務(http://symfony.com/doc/current/book/service_container.html)和注入學說。

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

話雖這麼說,我真的不明白這樣做的目的在您的情況作爲控制器是爲了獲取數據,並將其返回。

你沒有複製邏輯。

看起來太多了,實體經理已經是這樣的幫手。

+0

你是傳奇!謝謝,這正是我需要的! – b85411

+0

我很高興我能幫上忙! – LBridge

3

你真的沒有獲得任何你想寫的代碼。一個更好的做法是爲每個實體創建一個存儲庫類,並注入實體管理器。您還可以定義這些實體服務將擴展的另一個抽象存儲庫服務。我在我的應用程序中這樣做,我發現它非常有用,因爲我可以將自己的函數添加到我正在使用的存儲庫中。

我可以做這樣的事情在控制器:

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

@ Tobias的建議,工作正常,但你也應該考慮一個良好的初步實踐,說:「你需要僅注入服務」。

的這裏的一點是,你在注入實體管理拿到兩個學說庫tasks & tasksInfos),請記住,在實體管理器做多,僅檢索學說庫

當你的助手需要一個doctrine倉庫時,你通常會注入一個實體管理器,然後檢索你的倉庫。然而,你並沒有注入你所需要的服務,你正在注入一個經理,這可以幫助你獲得你需要的

另一個限制(可以考慮)是一個學說庫只能通過實體管理器進行檢索,所以我們有超過它的建設任何控制。

因此,注入存儲庫而不是實體管理器的唯一方法是考慮using Factory services and methods委託創建服務,然後注入相關服務。

那麼我會建議,

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

雖然你服務的定義應該看起來像,

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

優勢,

  • 你的代碼是乾淨的,更具可讀性爲你的服務的構造函數更具體地描述了它的實際需求。
  • 可測試性,您不必爲實體管理器和存儲庫創建模擬,而只需模擬您的存儲庫。