使用两个实体创建单个表单

时间:2014-06-19 21:44:54

标签: php symfony twig

我问了一个类似的问题,但我认为这引起了混乱,所以我决定在这篇文章中提出刷新版本。

我想要的是在一个网络表单中打印两个不同实体的所有字段, BOTH TYPE 。就是这样。

注意:我尝试在表单类型中使用entitycollection个关键字( BOTH TYPE ),但twig不会回显任何内容。继续; Method "brand" OR "car" for object does not exist in twig line whatever....

关系:1 Brand有N Cars。一个对多

enter image description here

我阅读了“如何嵌入表单集合”,“实体字段类型”'和'收集字段类型'但不管我做了什么,都没有用。

品牌实体

namespace Car\BrandBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

class BrandEntity
{
    protected $id;
    protected $name;
    protected $origin;

    /**
     * @ORM\OneToMany(targetEntity = "CarEntity", mappedBy = "brand")
     * @var object $car
     */
    protected $car;

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->car = new ArrayCollection();
    }
}

CAR ENTITY

namespace Car\BrandBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

class CarEntity
{
    protected $id;
    protected $model;
    protected $price;

    /**
     * @ORM\ManyToOne(targetEntity="BrandEntity", inversedBy="car")
     * @ORM\JoinColumn(name="brand_id", referencedColumnName="id")
     * @var object $brand
     */
    protected $brand;
}

品牌类型

namespace Car\BrandBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class BrandType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->setAction($options['action'])
            ->setMethod('POST')
            ->add('name', 'text', array('label' => 'Name'))
            ->add('origin', 'text', array('label' => 'Origin'))
            ->add('button', 'submit', array('label' => 'Add'))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Car\BrandBundle\Entity\BrandEntity')
        );
    }

    public function getName()
    {
        return 'brand';
    }
} 

CAR TYPE

namespace Car\BrandBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CarType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->setAction($options['action'])
            ->setMethod('POST')
            ->add('model', 'text', array('label' => 'Model'))
            ->add('price', 'text', array('label' => 'Price'))
            ->add('button', 'submit', array('label' => 'Add'))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Car\BrandBundle\Entity\CarEntity')
        );
    }

    public function getName()
    {
        return 'car';
    }
}

-------------------------------------------- -------------------------

--------此部分是我试图让它发挥作用的部分------

-------------------------------------------- -------------------------

BOTH TYPE

namespace Car\BrandBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Test\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class BothType extends AbstractType
{
    public function builder(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->setAction($options['action'])
            ->setMethod('POST')
            ->add('brand', 'collection', array('type' => new BrandType()))
            ->add('car', 'collection', array('type' => new CarType()))
            ->add('button', 'submit', array('label' => 'Add'))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Car\BrandBundle\Entity\BrandEntity',
            'cascade_validation' => true
        ));
    }

    public function getName()
    {
        return 'both';
    }
} 

CONTROLLER

namespace Car\BrandBundle\Controller;

use Car\BrandBundle\Form\Type\BothType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class BothController extends Controller
{
    public function indexAction()
    {
        $form = $this->createForm(new BothType(), null,
            array('action' => $this->generateUrl('bothCreate')));;

        return $this->render('CarBrandBundle:Default:both.html.twig',
                array('page' => 'Both', 'form' => $form->createView()));
    }
}

TWIG

{% block body %}
    {{ form_label(form.brand.name) }}
    {{ form_widget(form.brand.name) }}
    {{ form_label(form.brand.origin) }}
    {{ form_widget(form.brand.origin) }}

    {{ form_label(form.car.model) }}
    {{ form_widget(form.car.model) }}
    {{ form_label(form.car.price) }}
    {{ form_widget(form.car.price) }}
{% endblock %}

1 个答案:

答案 0 :(得分:1)

使用数组合成控制器中的两个对象。

$formData = array(
    'brand' = new Brand(),
    'car' => new Car(),
);
$builder = $this->createFormBuilder($formData);
$builder->add('brand',new BrandFormType());
$builder->add('car', new CarFormType());

$form = $builder->getForm();

==============================================================
If you really want to make a BothType then just get rid of that collection type.

class BothType extends AbstractType
{
    public function builder(FormBuilderInterface $builder, array $options)
    {
    $builder
        ->setAction($options['action'])
        ->setMethod('POST')
        ->add('brand', new BrandType())
        ->add('car', new CarType())
        ->add('button', 'submit', array('label' => 'Add'))
    ;
    }

    // Controller
    $form = $this->createForm(new BothType(), $formData
如果您有多个相同实体类型的实例,则使用

集合。

顺便说一句,为每个复合表单创建类可能会很快导致表单类型的爆炸。因此,除非您计划在多个控制器之间重用您的BothFormType,否则我建议您只在控制器内部构建它。