我如何将定制的学说存储库绑定到 symfony 中的映射实体?
How can I tie bespoke doctrine repositories to mapped entities in 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:
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();
}
}
现在,如果这是一个只有一个部门的页面,我只需在我的控制器中调用自定义查询,然后将其拉入视图。
然而,我向所有部门展示了他们所有迫在眉睫的任务,这让控制器有点不整洁,因为这会迫使我建立一个部门及其任务的数组。
考虑到目前我只需要在 twig 中循环 department.tasks
并且它知道提取与部门实体相关的任务,这感觉很难看。
我也知道我不应该(也不能轻易)在我的部门实体的存储库中调用自定义查询。
所以我想知道的是 - 我能否以某种方式将定制查询绑定到相关实体,以便原则知道当我向部门请求任务时,它必须去而不是得到除定义的子集?
理想情况下,我希望能够通过调用 tasksDueSoon
之类的东西来绕过如下所示的树枝模板,而不必向控制器(或其他地方)添加额外的逻辑负载.
{% for department in departments %}
{% for task in department.tasksDueSoon %}
...
{% endfor %}
{% endfor %}
如果那不可能,我必须通过控制器沿着自定义数组的路径走下去,这当然很好,但感觉不对,所以希望在 Syomfony 中有更好的方法来做到这一点,并告诉部门实体使用任务存储库或其他东西。
部门 class 中有一个关于你的任务 属性 的 @OrderBy
-annotation,但据我所知,你不能将其设为更复杂的查询。
我通常做的是创建另一个 getter,它使用 Collection Criteria 过滤掉我想要的 children。
当然这有一些开销,因为它对从存储库中获取的所有任务进行操作,但我发现在大多数情况下,性能对于我通常操作的规模来说仍然非常好。当它变慢时我通常会退回到您不喜欢的当前解决方案,甚至更进一步,并在必要时使用 NativeQuery and/or 部分结果。
我只想在 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;
}
并且只需在 Twig 模板中使用它:
{% for department in departments %}
{% for task in department.tasksOrderedByDueDate %}
...
{% endfor %}
{% endfor %}
现在除非它成为一个真正的问题,否则不要担心性能。
我总是在不测试实际代码的情况下犹豫 post 一个答案,但这里是。诀窍是在加载部门的同时加载最近的任务。
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();
我有两个实体。任务和部门。
一个部门可以有很多任务。
/**
* @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:
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();
}
}
现在,如果这是一个只有一个部门的页面,我只需在我的控制器中调用自定义查询,然后将其拉入视图。
然而,我向所有部门展示了他们所有迫在眉睫的任务,这让控制器有点不整洁,因为这会迫使我建立一个部门及其任务的数组。
考虑到目前我只需要在 twig 中循环 department.tasks
并且它知道提取与部门实体相关的任务,这感觉很难看。
我也知道我不应该(也不能轻易)在我的部门实体的存储库中调用自定义查询。
所以我想知道的是 - 我能否以某种方式将定制查询绑定到相关实体,以便原则知道当我向部门请求任务时,它必须去而不是得到除定义的子集?
理想情况下,我希望能够通过调用 tasksDueSoon
之类的东西来绕过如下所示的树枝模板,而不必向控制器(或其他地方)添加额外的逻辑负载.
{% for department in departments %}
{% for task in department.tasksDueSoon %}
...
{% endfor %}
{% endfor %}
如果那不可能,我必须通过控制器沿着自定义数组的路径走下去,这当然很好,但感觉不对,所以希望在 Syomfony 中有更好的方法来做到这一点,并告诉部门实体使用任务存储库或其他东西。
部门 class 中有一个关于你的任务 属性 的 @OrderBy
-annotation,但据我所知,你不能将其设为更复杂的查询。
我通常做的是创建另一个 getter,它使用 Collection Criteria 过滤掉我想要的 children。
当然这有一些开销,因为它对从存储库中获取的所有任务进行操作,但我发现在大多数情况下,性能对于我通常操作的规模来说仍然非常好。当它变慢时我通常会退回到您不喜欢的当前解决方案,甚至更进一步,并在必要时使用 NativeQuery and/or 部分结果。
我只想在 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;
}
并且只需在 Twig 模板中使用它:
{% for department in departments %}
{% for task in department.tasksOrderedByDueDate %}
...
{% endfor %}
{% endfor %}
现在除非它成为一个真正的问题,否则不要担心性能。
我总是在不测试实际代码的情况下犹豫 post 一个答案,但这里是。诀窍是在加载部门的同时加载最近的任务。
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();