Symfony2 表单 - 如何呈现所有可以链接到具有附加字段的当前实体的实体
Symfony2 forms - how to render all entities that can be linked to current entity with additional field
我需要实现有趣的功能,但我不知道正确的解决方案。看下面的例子。
我有 2 个实体:
- 车辆(可以是汽车、火车、自行车或腿或其他东西)
- 零件(可以是线圈、轮子、座椅、window、手刹等...)
当我创建或编辑车辆时,我应该可以为该车辆选择任何零件的数量。因此,Vehicle 表单应包含所有 Parts,并且每个 Part 应具有附加字段 'amount'。
因此,如果 amount 大于 0,则应创建关系。如果零件数量等于零 - 在该零件和载具之间没有要创建的关系。
很公平,我创建了额外的实体来存储与额外字段的关系:
- VehiclePart(它存储vehicle_id、part_id和这部分的数量)
此实体通过 ManyToOne 关系与 Vehicle 和 Part 实体链接
有一个问题:我如何以车辆形式渲染所有可用零件,以及当零件数量 > 0 时如何实现检查以保持关系?
我需要建议 - 满足我需求的正确方法是什么?真的很抱歉我的英语
这里有一个方法供您尝试。
您可以使用 this method from the Symfony documentation 制作表格。这会很好用,因为它允许您从所有可用零件的 select 列表中即时将零件添加到您的车辆。
这样,如果数量 > 0,您就不必担心持续存在,如果您添加零件和数量,它就会被添加。要将数量归零,您只需完全移除零件即可。
你原来的想法没那么简单。您必须使用 form events 动态添加表单字段。在保存表单时,您可以使用表单事件侦听器来访问底层 Vehicle 实体,然后在保留数据之前删除任何数量为 0 的 VehiclePart 实体。
这样做没问题,但我会推荐第一个选项,因为它简单得多。
编辑:添加了基本概述。由于时间不够,所以很粗糙!
侦听器添加字段
<?php
namespace Your\NameSpace\Form\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AddYourTypeSubscriber implements EventSubscriberInterface
{
private $factory;
public function __construct(FormFactoryInterface $factory) {
$this->factory = $factory;
}
public static function getSubscribedEvents() {
return array(FormEvents::PRE_SET_DATA => 'addYourItem');
}
public function addYourItem(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (!$data instanceof YourClass) {
return;
}
/** @var YourClass $yourClassItem */
$yourClassItem = $data;
// You might have some criteria around what you would or would not add
$form->add(
$this->factory->createNamed('yourChildPropertyOrCollectionField', new YourChildPropertyOrCollectionFieldFormType() /** also could be a form type service */, null, array('auto_initialize' => false))
);
}
}
侦听器根据某些条件删除与字段相关的数据)
<?php
namespace Your\NameSpace\Form\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class RemoveTypeBasedOnSomeCriteriaSubscriber implements EventSubscriberInterface
{
private $factory;
public function __construct(FormFactoryInterface $factory) {
$this->factory = $factory;
}
public static function getSubscribedEvents() {
return array(FormEvents::POST_SUBMIT => 'removeItemsBasedOnSomeCriteria');
}
/**
* Remove items we do not want
*
* @param FormEvent $event
*/
public function removeItemsBasedOnSomeCriteria(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (!$data instanceof YourClass) {
return;
}
// If the form isn't valid we don't need to action this as we have
// yet to persist.
if (!$form->isValid()) {
return;
}
// From here you can do anything with YourClass
if ($yourClass->failsSomeCriteria()) {
$yourClass->setSomeChildProperty(null); // etc
}
}
}
然后只需将订阅者添加到您要将其附加到的表单类型即可。
// add item subscriber in buildform method of your form type
$addYourSubscriberSubscriber = new AddYourTypeSubscriber($builder->getFormFactory());
$builder->addEventSubscriber($addYourSubscriberSubscriber);
// remove item subscriber in buildform method of your form type
$removeTypeBasedOnSomeCriteriaSubscriber = new RemoveTypeBasedOnSomeCriteriaSubscriber($builder->getFormFactory());
$builder->addEventSubscriber($removeTypeBasedOnSomeCriteriaSubscriber);
我需要实现有趣的功能,但我不知道正确的解决方案。看下面的例子。
我有 2 个实体:
- 车辆(可以是汽车、火车、自行车或腿或其他东西)
- 零件(可以是线圈、轮子、座椅、window、手刹等...)
当我创建或编辑车辆时,我应该可以为该车辆选择任何零件的数量。因此,Vehicle 表单应包含所有 Parts,并且每个 Part 应具有附加字段 'amount'。 因此,如果 amount 大于 0,则应创建关系。如果零件数量等于零 - 在该零件和载具之间没有要创建的关系。
很公平,我创建了额外的实体来存储与额外字段的关系:
- VehiclePart(它存储vehicle_id、part_id和这部分的数量)
此实体通过 ManyToOne 关系与 Vehicle 和 Part 实体链接
有一个问题:我如何以车辆形式渲染所有可用零件,以及当零件数量 > 0 时如何实现检查以保持关系?
我需要建议 - 满足我需求的正确方法是什么?真的很抱歉我的英语
这里有一个方法供您尝试。
您可以使用 this method from the Symfony documentation 制作表格。这会很好用,因为它允许您从所有可用零件的 select 列表中即时将零件添加到您的车辆。
这样,如果数量 > 0,您就不必担心持续存在,如果您添加零件和数量,它就会被添加。要将数量归零,您只需完全移除零件即可。
你原来的想法没那么简单。您必须使用 form events 动态添加表单字段。在保存表单时,您可以使用表单事件侦听器来访问底层 Vehicle 实体,然后在保留数据之前删除任何数量为 0 的 VehiclePart 实体。
这样做没问题,但我会推荐第一个选项,因为它简单得多。
编辑:添加了基本概述。由于时间不够,所以很粗糙!
侦听器添加字段
<?php
namespace Your\NameSpace\Form\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AddYourTypeSubscriber implements EventSubscriberInterface
{
private $factory;
public function __construct(FormFactoryInterface $factory) {
$this->factory = $factory;
}
public static function getSubscribedEvents() {
return array(FormEvents::PRE_SET_DATA => 'addYourItem');
}
public function addYourItem(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (!$data instanceof YourClass) {
return;
}
/** @var YourClass $yourClassItem */
$yourClassItem = $data;
// You might have some criteria around what you would or would not add
$form->add(
$this->factory->createNamed('yourChildPropertyOrCollectionField', new YourChildPropertyOrCollectionFieldFormType() /** also could be a form type service */, null, array('auto_initialize' => false))
);
}
}
侦听器根据某些条件删除与字段相关的数据)
<?php
namespace Your\NameSpace\Form\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class RemoveTypeBasedOnSomeCriteriaSubscriber implements EventSubscriberInterface
{
private $factory;
public function __construct(FormFactoryInterface $factory) {
$this->factory = $factory;
}
public static function getSubscribedEvents() {
return array(FormEvents::POST_SUBMIT => 'removeItemsBasedOnSomeCriteria');
}
/**
* Remove items we do not want
*
* @param FormEvent $event
*/
public function removeItemsBasedOnSomeCriteria(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (!$data instanceof YourClass) {
return;
}
// If the form isn't valid we don't need to action this as we have
// yet to persist.
if (!$form->isValid()) {
return;
}
// From here you can do anything with YourClass
if ($yourClass->failsSomeCriteria()) {
$yourClass->setSomeChildProperty(null); // etc
}
}
}
然后只需将订阅者添加到您要将其附加到的表单类型即可。
// add item subscriber in buildform method of your form type
$addYourSubscriberSubscriber = new AddYourTypeSubscriber($builder->getFormFactory());
$builder->addEventSubscriber($addYourSubscriberSubscriber);
// remove item subscriber in buildform method of your form type
$removeTypeBasedOnSomeCriteriaSubscriber = new RemoveTypeBasedOnSomeCriteriaSubscriber($builder->getFormFactory());
$builder->addEventSubscriber($removeTypeBasedOnSomeCriteriaSubscriber);