2017-09-07 54 views
1

我有兩個實體。任務和部門。如何將定製的原則庫與symfony中的映射實體綁定?

一個部門可以有很多任務。

/** 
* @ORM\Entity 
* @ORM\Table(name="departments") 
*/ 
class Department 
{ 
    /** 
    * @ORM\OneToMany(targetEntity="Task", mappedBy="department") 
    */ 
    public $tasks; 

    /** 
    * @return ArrayCollection|Task[] 
    */ 
    public function getTasks() 
    { 
     return $this->tasks; 
    } 
} 

/** 
* @ORM\Entity 
* @ORM\Table(name="tasks") 
*/ 
class Task 
{ 
    /** 
    * @ORM\ManyToOne(targetEntity="Department", inversedBy="tasks") 
    */ 
    public $department; 

    /** 
    * @return Department 
    */ 
    public function getDepartment() 
    { 
     return $this->department; 
    } 
} 

我也有一個視圖,顯示所有部門及其相關任務。

{% for department in departments %} 
    {% for task in department.tasks %} 
     ... 
    {% endfor %} 
{% endfor %} 

然後這給我幾列,每個填充任務。

我現在想改變這個,以便每列只顯示按截止日期排序的最迫切的任務(一週內到期)。

爲此我已經創建了TaskRepository類自定義查詢:現在

class TaskRepository extends EntityRepository 
{ 
    /** 
    * @param Department $department 
    * @return Task[] 
    */ 
    public function findAllRecentTasksForGenus(Department $department) 
    { 
     return $this->createQueryBuilder('task') 
      ->andWhere('task.department = :department') 
      ->setParameter('department', $department) 
      ->andWhere('task.dueDate> :dueDate') 
      ->setParameter('dueDate', new \DateTime('-1 week')) 
      ->orderBy('task.dueDate', 'DESC') 
      ->getQuery() 
      ->execute(); 
    } 
} 

,如果這是一個網頁,只是一個部門,我只想叫我的控制器中的自定義查詢,拉那進入視野。

但是,我向所有部門顯示所有即將到來的任務,這使得控制器中有點不整潔,因爲這會迫使我建立一系列部門及其任務。

考慮到目前我只需要繞過department.tasks而感到難看,並且它知道要抽取與部門實體相關的任務。

我也知道我不應該(也不能輕易地)在我的部門實體中調用存儲庫中的自定義查詢。

所以我試圖找出的是 - 我可以以某種方式綁定定製的查詢,如描述到相關的實體,以便學說知道,當我要求部門上的任務,它必須去除,而不是所有的定義子集?

理想情況下,我想能夠通過調用類似tasksDueSoon繞過中包含一個樹枝模板結束,而無需額外的邏輯負荷添加到控制器(或其他地方爲此事。

{% for department in departments %} 
    {% for task in department.tasksDueSoon %} 
     ... 
    {% endfor %} 
{% endfor %} 

如果這是不可能的,我必須通過控制器走下自定義數組的路線,這當然是好的,但感覺不對,所以希望有更好的方法在Syomfony中做到這一點,並告訴部門實體使用任務庫或其他東西

+0

將您的查詢移動到部門存儲庫並將其命名爲findDepartmentsWithRecentTasks。在select子句中,添加'task'。所以現在當你查詢你的部門時,他們只包括最近的任務。無需更改枝條模板。 – Cerad

+0

@Cerad - 基本上我正在尋找的東西,但我無法安靜地開始工作。你介意用示例代碼添加一個答案嗎? – Bananaapple

回答

1

我總是毫不猶豫地發佈一個答案,而沒有測試實際的代碼,但在這裏。訣竅是在加載部門的同時加載最近的任務。

class DepartmentRepository 
{ 
    findDepartmentsAlongWithRecentTasks() 
    { 
     $qb = $this->createQueryBuilder('dept'); 
     $qb->select('dept','task'); 
     $qb->leftJoin('dept.tasks','task'); 

     $qb->andWhere('task.dueDate > :dueDate') 
      ->setParameter('dueDate', new \DateTime('-1 week')) 
      ->orderBy('task.dueDate', 'DESC'); 

     return $qb->getQuery()->execute(); 
+0

啊,然後在部門的控制器中調用,而不是findAll! – Bananaapple

+1

有一個問題。如果一個部門沒有最近的任務,那麼它將不會被加載。如果這很重要,則需要使用不同的連接。 – Cerad

+0

是啊沒有擔心得到了覆蓋 - 主要是調用控制器中的回購方法來加載所需的數據:-) – Bananaapple

2

有一個@OrderBy-annotation你的任務p在部門類的屬性,但據我所知,你不能使這個更復雜的查詢。

我通常會做的是創建另一個吸氣劑,使用Collection Criteria過濾掉我想要的孩子。

當然這有一些開銷,因爲它對從倉庫取得的所有任務進行操作,但是我發現在大多數情況下,對於我通常使用的秤來說,性能仍然非常好。回退到您不喜歡的甚至更進一步的當前解決方案,並在必要時使用NativeQuery和/或部分結果。

1

我只是在Department實體中創建一個方法getTasksOrderedByDueDate()什麼的。可能比SQL查詢性能稍差,但對我來說似乎更清晰。

public function getTasksOrderedByDueDate(): array 
{ 
    $tasks = $this->getTasks(); 
    usort($tasks, function (Task $a, Task $b) { 
     return $a->getDueDate()->getTimestamp() - $b->getDueDate()->getTimestamp(); 
    }); 

    return $tasks; 
} 

,簡單地在樹枝模板中使用這樣的:

{% for department in departments %} 
    {% for task in department.tasksOrderedByDueDate %} 
     ... 
    {% endfor %} 
{% endfor %} 

現在,除非它成爲一個真正的問題,不用擔心性能。

相關問題