是否在symfony4表单中的CollectionType上使用查询生成器?
在symfony4表单中,我需要使用类似于是否在symfony4表单中的CollectionType上使用查询生成器?,symfony,symfony4,Symfony,Symfony4,在symfony4表单中,我需要使用类似于query\u builder的选项,该选项在EntityType上可用,但来自CollectionType。有一个类似的问题没有很好的答案 在我的项目中,每个站点实体都有许多目标。每个目标都有一个数字目标和一个特定日期。我只想编辑特定日期的网站目标。问题是CollectionType表单会将所有目标拉入表单中显示,但我只想拉入给定日期的目标。怎么用?在CollectionType上没有像在EntityType上那样的query\u builder。我可
query\u builder
的选项,该选项在EntityType
上可用,但来自CollectionType
。有一个类似的问题没有很好的答案
在我的项目中,每个站点
实体都有许多目标
。每个目标都有一个数字目标和一个特定日期。我只想编辑特定日期的网站目标。问题是CollectionType表单会将所有目标拉入表单中显示,但我只想拉入给定日期的目标。怎么用?在CollectionType
上没有像在EntityType上那样的query\u builder
。我可以在我的站点实体中更改getter,但我不知道如何将所需的日期传递给getter
目前,我的工作是呈现整个表单(带有给定站点的所有相关目标),然后使用一些javascript隐藏所有目标,除了那些带有编辑日期的目标。这是可行的,但对于那些目标跨越一系列日期的网站来说,这是一个糟糕的解决方案
我的网站
实体(仅显示相关代码):
以及我的相关目标
实体:
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
表单的和选项的同时,使用可能会使您处于正确的环境中:
首先-为了方便起见,让我们假设我们是按年份过滤的,并且年份是从?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]);
// ...
}
然后,在同一类的buildForm
方法中,我们可以访问站点
对象,并从中删除目标
,其中目标日期的年份不在表单的
<?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,
]);
}
);
}
// ...
}
使用要在集合类型上设置的控制器中的实体管理器过滤结果
$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]);
我认为,CollectionType
的选项意味着提交的表单数据属于集合中的所有实体。在特定的日期范围内只编辑Goal
s可能在CollectionType
之外做得更好。实际上,我可能完全错了!如果编辑(而不是删除或添加新内容)是路线中这些目标的唯一关注点,那么最好使用!谢谢@Cameronhard。你是对的,我不需要在这个应用程序中添加/删除目标,我只需要编辑现有的目标。表单事件的想法很有趣,但很难看到如何应用于整个实体数组和相关参数。哇,这是严重的symfony表单巫毒!!非常感谢,它工作得很好。
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('goals', Type\CollectionType::class, [
'entry_type' => GoalsEmbeddedType::class,
'data' => $options['goals'],
'mapped` => false
]);
}
$goals = $entityManager->getRepository(Goals::class)->findBy(['year' => 2020]);