在symfony 4格式中,我需要使用类似query_builder
的选项,该选项在EntityType
上可用,但可以在CollectionType
上使用。存在类似的问题here,但没有很好的答案。
在我的项目中,每个Site
实体都有许多Goal
。每个Goal
都有一个数字目标和一个特定日期。我只想编辑特定日期的网站目标。问题在于,CollectionType表单会提取 all 个目标以在表单中显示,但是我只想在给定日期内提取目标。怎么样? query_builder
上没有CollectionType
上的EntityType
。我可以在Site实体中更改吸气剂,但是我不知道如何将所需的日期传递给吸气剂。
现在,我的解决方法是呈现整个表单(具有给定站点的所有关联目标),然后使用一些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,
]);
}
}
答案 0 :(得分:1)
使用Form Events,同时避免使用CollectionType
表单的allow_add
和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
类的默认选项:
<?php
// SiteGoalsAdminForm.php
// ...
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Site::class,
'year_filter' => 2018
]);
}
// ...
然后,在同一类的buildForm
方法中,我们可以访问Site
对象,并从其中删除Goals
,如果目标日期的年份不属于表单的< / p>
<?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,但功能相似。
答案 1 :(得分:0)
使用要在集合类型上设置的控制器中的实体管理器过滤结果。
$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']);
}
在buildForm
的{{1}}方法中,通过选项将数据设置为“收集类型”字段。
SiteGoalsType::class
确保将public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('goals', Type\CollectionType::class, [
'entry_type' => GoalsEmbeddedType::class,
'data' => $options['goals'],
'mapped` => false
]);
}
添加到您的收集类型字段中,否则可能导致删除未归入我们在控制器中编写的过滤器中的记录。
'mapped' => false