2017-09-07 7 views
1

두 엔티티가 있습니다. 작업 및 부서.맞춤 교리 저장소를 심포니에 매핑 된 엔티티에 어떻게 연결시킬 수 있습니까?

하나의 부서는 많은 작업을 수행 할 수 있습니다.

/** 
* @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 이상의 루프가 필요하고 부서 엔티티와 관련된 작업을 가져 오는 것을 알고 있기 때문에 추한 느낌입니다.

또한 내 부서 엔티티의 리포지토리에서 사용자 지정 쿼리를 호출하면 안된다는 것을 알고 있습니다.

그래서 내가 알아 내려고하는 것은 - 관련 엔터티에 설명 된 맞춤식 쿼리를 어떻게 든 바인딩 할 수 있습니다. 따라서 Doctrine은 부서에서 작업을 요청할 때 정의 된 것 이외에는 모두 가져와야한다는 것을 알고 있습니다. 하위 집합?

은 이상적으로는 컨트롤러에 추가 로직의 부하를 추가 할 필요없이 (또는 다른 곳에서 그 문제에 tasksDueSoon 같은 뭔가를 호출하여 아래와 같이 나뭇 가지 템플릿을 끝낼 우회 할 수 있도록하고 싶습니다.

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

그럴 수 없다면 컨트롤러를 통해 사용자 지정 배열 경로를 따라 가야합니다. 물론 잘못된 것 같습니다.하지만 Syomfony에서이 작업을 수행하고 Department 엔터티에 사용하도록 더 좋은 방법이 있기를 바랍니다. 작업 저장소 또는 무언가.

+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

그래 걱정할 필요는 없습니다 - 주요한 것은 컨트롤러의 repo 메소드를 호출하여 원하는 데이터를로드하는 것입니다 :-) – Bananaapple

2

작업 p에 @OrderBy-annotation이 있습니다. 부서 클래스의 고급 기능을 제공하지만, 내가 아는 한 더 복잡한 쿼리를 작성할 수는 없습니다.

내가 일반적으로하고 싶은 것은 Collection Criteria을 사용하여 원하는 자식을 걸러내는 또 다른 게터를 만드는 것입니다.

이것은 저장소에서 가져온 모든 작업에서 작동하므로 약간의 오버 헤드가 있음을 알았지 만, 대부분의 경우 성능은 일반적으로 일반적으로 작동하는 규모의 경우에도 여전히 완벽합니다. 싫어하거나 현재의 솔루션으로 돌아가서 필요에 따라 NativeQuery 및/또는 부분 결과를 사용하십시오.

1

난 그냥 부서 엔티티, 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 %} 

을 지금은 실제 문제가됩니다하지 않는 한, 성능에 대해 걱정하지 마십시오.