在 symfony4 形式的 CollectionType 上使用 query_builder?
Use query_builder on CollectionType in symfony4 forms?
在 symfony 4 形式中,我需要使用类似 query_builder
的选项,它在 EntityType
上可用,但在 CollectionType
上可用。有一个类似的问题 没有很好的答案。
在我的项目中,每个 Site
个实体有多个 Goal
。每个 Goal
都有一个数字目标和一个特定日期。我只想编辑特定日期的网站目标。问题是 CollectionType 表单会提取 all 目标以在表单中显示,但我只想提取给定日期的目标。如何? CollectionType
上没有 query_builder
,而 EntityType
上有。我可以更改我的站点实体中的 getter,但我不知道如何将所需日期传递给我的 getter。
目前我的解决方法是呈现整个表单(包含给定站点的所有关联目标),然后使用一些 javascript 隐藏所有目标,但带有编辑日期的目标除外。这行得通,但对于具有跨越一系列日期的大量目标的网站来说,这是一个糟糕的解决方案。
我的 Site
实体(仅显示相关代码):
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,
]);
}
}
对 CollectionType
表单使用 Form Events, while avoiding the allow_add
and allow_delete
选项可能会让您进入正确的社区:
首先 - 假设我们按年份过滤,为了便于示例,并且年份是从 ?y=2018
样式的查询字符串中获取的。我们将该信息传递给表单生成器:
<?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
class:
的默认选项
<?php
// SiteGoalsAdminForm.php
// ...
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Site::class,
'year_filter' => 2018
]);
}
// ...
然后,在同一个 class 的 buildForm
方法中,我们可以访问 Site
对象并从目标日期所在的年份移除 Goals
不属于表格的
<?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,但功能相似。
使用要在集合类型上设置的控制器中的实体管理器过滤结果。
$goals = $entityManager->getRepository(Goals::class)->findBy(['year' => 2020]);
$form = $this->createForm(SiteGoalsType::class, $site, [
'goals' => $goals
]);
然后配置 SiteGoalsType::class
以接受新的选项目标。
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Site::class,
]);
$resolver->setRequired(['goals']);
}
在SiteGoalsType::class
的buildForm
方法中,将数据设置为选项中的集合类型字段。
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('goals', Type\CollectionType::class, [
'entry_type' => GoalsEmbeddedType::class,
'data' => $options['goals'],
'mapped` => false
]);
}
确保将 'mapped' => false
添加到您的集合类型字段,否则它可能会导致删除不属于我们在控制器中编写的过滤器的记录。
$goals = $entityManager->getRepository(Goals::class)->findBy(['year' => 2020]);
在 symfony 4 形式中,我需要使用类似 query_builder
的选项,它在 EntityType
上可用,但在 CollectionType
上可用。有一个类似的问题
在我的项目中,每个 Site
个实体有多个 Goal
。每个 Goal
都有一个数字目标和一个特定日期。我只想编辑特定日期的网站目标。问题是 CollectionType 表单会提取 all 目标以在表单中显示,但我只想提取给定日期的目标。如何? CollectionType
上没有 query_builder
,而 EntityType
上有。我可以更改我的站点实体中的 getter,但我不知道如何将所需日期传递给我的 getter。
目前我的解决方法是呈现整个表单(包含给定站点的所有关联目标),然后使用一些 javascript 隐藏所有目标,但带有编辑日期的目标除外。这行得通,但对于具有跨越一系列日期的大量目标的网站来说,这是一个糟糕的解决方案。
我的 Site
实体(仅显示相关代码):
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,
]);
}
}
对 CollectionType
表单使用 Form Events, while avoiding the allow_add
and allow_delete
选项可能会让您进入正确的社区:
首先 - 假设我们按年份过滤,为了便于示例,并且年份是从 ?y=2018
样式的查询字符串中获取的。我们将该信息传递给表单生成器:
<?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
class:
<?php
// SiteGoalsAdminForm.php
// ...
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Site::class,
'year_filter' => 2018
]);
}
// ...
然后,在同一个 class 的 buildForm
方法中,我们可以访问 Site
对象并从目标日期所在的年份移除 Goals
不属于表格的
<?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,但功能相似。
使用要在集合类型上设置的控制器中的实体管理器过滤结果。
$goals = $entityManager->getRepository(Goals::class)->findBy(['year' => 2020]);
$form = $this->createForm(SiteGoalsType::class, $site, [
'goals' => $goals
]);
然后配置 SiteGoalsType::class
以接受新的选项目标。
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Site::class,
]);
$resolver->setRequired(['goals']);
}
在SiteGoalsType::class
的buildForm
方法中,将数据设置为选项中的集合类型字段。
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('goals', Type\CollectionType::class, [
'entry_type' => GoalsEmbeddedType::class,
'data' => $options['goals'],
'mapped` => false
]);
}
确保将 'mapped' => false
添加到您的集合类型字段,否则它可能会导致删除不属于我们在控制器中编写的过滤器的记录。
$goals = $entityManager->getRepository(Goals::class)->findBy(['year' => 2020]);