在 symfony4 形式的 CollectionType 上使用 query_builder ? [英] Use query_builder on CollectionType in symfony4 forms?
问题描述
在 symfony 4 形式中,我需要使用类似 query_builder
的选项,该选项在 EntityType
上可用,但来自 CollectionType
.此处有一个类似的问题,但没有很好的答案.
In a symfony 4 form, I need to use something like a query_builder
option that is available on EntityType
but from a CollectionType
. There is a similar question here with no good answers.
在我的项目中,每个Site
实体都有许多Goal
.每个 Goal
都有一个数字目标和一个特定的日期.我只想编辑特定日期的网站目标.问题是 CollectionType 表单将 all 目标拉入表单中,但我只想拉出给定日期的目标.如何?CollectionType
上没有 query_builder
,就像在 EntityType
上一样.我可以更改 Site 实体中的 getter,但我不知道如何将所需的日期传递给我的 getter.
In my project, each Site
entity has many Goal
. Each Goal
has a numeric goal and a specific date. I'd like to edit the goals of a site for a specific date only. The problem is that a CollectionType form pulls all goals to show in the form, but I only want to pull the goals for a given date. How? There is no query_builder
on a CollectionType
like there is on an EntityType
. I could change the getter in my Site entity, but I don't know how to pass the needed date to my getter.
现在我的解决方法是呈现整个表单(包含给定站点的所有相关目标),然后使用一些 javascript 隐藏所有目标,但要编辑日期的目标除外.这是有效的,但对于具有跨越多个日期范围的大量目标的网站来说,这是一个糟糕的解决方案.
For now my work-around is to render the entire form (with ALL associated goals for a given site), and then use some javascript to hide all goals except those with the date to edit. This works, but it's a terrible solution for sites with lots of goals spanning a range of dates.
我的 Site
实体(仅显示相关代码):
My Site
entity (only relevant code is shown):
class Site
{
public function __construct()
{
$this->goals = new ArrayCollection();
}
/** @ORM\OneToMany(targetEntity="App\Entity\Goal", mappedBy="site") */
private $goals;
public function getGoals()
{
return $this->goals;
}
}
和我相关的Goal
实体:
class Goal
{
/** @ORM\Column(type="date") */
private $goalDate;
/** @ORM\Column(type="integer") */
private $goal;
/** @ORM\ManyToOne(targetEntity="App\Entity\Site", inversedBy="goals") */
private $site;
// ...
}
我的表格:
class SiteGoalsAdminForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('goals', CollectionType::class, [
'entry_type' => GoalsEmbeddedForm::class,
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Site::class
]);
}
}
和个人目标形式:
class GoalsEmbeddedForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('goal', IntegerType::class)
->add('goalDate', DateType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Goal::class,
]);
}
}
推荐答案
使用 表单事件,同时避免 allow_add
和 CollectionType 表单的nofollow noreferrer">allow_delete
选项可能会让您找到正确的社区:
Using Form Events, while avoiding the allow_add
and allow_delete
options for the CollectionType
form might land you in the right neighbourhood:
首先 - 让我们假设我们按年份过滤,以方便示例,并且年份是从 ?y=2018
样式的查询字符串中提取的.我们会将这些信息传递给表单构建器:
First - let's assume we're filtering by year, for ease of example, and that the year is being scooped up from a ?y=2018
style of querystring. We'll pass that info down to the form builder:
<?php
// Inside a *Action method of a controller
public function index(Request $request): Response
{
// ...
$filteredYear = $request->get('y');
$form = $this->createForm(SiteGoalsAdminForm::class, $site, ['year_filter' => $filteredYear]);
// ...
}
这意味着我们应该更新 SiteGoalsAdminForm
类的默认选项:
This implies we should be updating the default options for the SiteGoalsAdminForm
class:
<?php
// SiteGoalsAdminForm.php
// ...
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Site::class,
'year_filter' => 2018
]);
}
// ...
然后,在同一个类的 buildForm
方法中,我们可以访问 Site
对象并从中删除 Goals
目标日期不属于表单的
Then, in the buildForm
method of that same class, we could access the Site
object and remove Goals
from it where the year of the goalDate did not fall inside the form's
<?php
// SiteGoalsAdminForm.php
namespace App\Form;
// ... other `use` statements, plus:
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class SiteGoalsAdminForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($options) {
$form = $event->getForm();
/** @var Site */
$site = $event->getData();
$goals = $site->getGoals();
foreach ($goals as $g) {
if ($g->getGoalDate()->format('Y') !== (string) $options['year_filter']) {
$site->removeGoal($g);
}
}
$form->add('goals', CollectionType::class, [
'entry_type' => GoalsEmbeddedForm::class,
]);
}
);
}
// ...
}
不完全是 query_builder,但功能相似.
Not a query_builder exactly, but functionally similar.
这篇关于在 symfony4 形式的 CollectionType 上使用 query_builder ?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!