Symfony2 表单 - 如何呈现所有可以链接到具有附加字段的当前实体的实体

Symfony2 forms - how to render all entities that can be linked to current entity with additional field

我需要实现有趣的功能,但我不知道正确的解决方案。看下面的例子。

我有 2 个实体:

当我创建或编辑车辆时,我应该可以为该车辆选择任何零件的数量。因此,Vehicle 表单应包含所有 Parts,并且每个 Part 应具有附加字段 'amount'。 因此,如果 amount 大于 0,则应创建关系。如果零件数量等于零 - 在该零件和载具之间没有要创建的关系。

很公平,我创建了额外的实体来存储与额外字段的关系:

此实体通过 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);