如何在symfony2中使用一个按钮提交多个相同类型的表单

Ran*_*ngh 6 symfony doctrine-orm

我有todolist,我显示三种形式的任务类型

$task1 = new Task();
$form1 = $this->createForm(new MyForm('f1'), $task1);

$task2 = new Task('fo');
$form2 = $this->createForm(new MyForm('f2'), $task2);

$task3 = new Task();
$form3 = $this->createForm(new MyForm('f3'), $task3);
Run Code Online (Sandbox Code Playgroud)

现在问题是我只有一个提交按钮.如何在一个控制器中保留这三个任务.用户也可以动态添加更多表单.

那么解决这个问题的方法是什么

Eln*_*mov 5

创建一个Form Model类 - 就像TaskList- 包含一个Tasks 的集合.然后创建TaskListType用于保存收集TaskType秒.这样,您将拥有一个包含任意数量的任务的表单.


Fra*_*ula 5

为了完整起见,请在下面找到一个完整的例子.

您应该创建一个表示所需表单的新模型.关键是你可能不想影响Doctrine(例如,参见doctrine:schema:update命令).它可能会尝试为实际不存在的实体创建表.为避免这种情况,只需将模型类放在Model文件夹下(\ src\Acme\Bundle\DemoBundle\Model\TaskList.php).

假设以下是您的TaskType表单类:

<?php

namespace Acme\Bundle\DemoBundle\Form;

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

class TaskType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('id', null, array('read_only' => true))
            ->add('name');
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(
            array(
                'data_class' => 'Acme\Bundle\DemoBundle\Entity\Task'
            )
        );
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'acme_demo_task';
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该是你的TaskList模型类:

<?php

namespace Acme\Bundle\DemoBundle\Model;

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

/**
 * Class TaskList
 * @package Acme\Bundle\DemoBundle\Model
 *
 * @ORM\Entity()
 */
class TaskList
{
    /**
     * @var \Doctrine\Common\Collections\ArrayCollection
     * @ORM\ManyToMany(targetEntity="\Acme\Bundle\DemoBundle\Entity\Task")
     */
    private $tasks;

    public function __construct()
    {
        $this->tasks = new ArrayCollection();
    }

    /**
     * @param \Acme\Bundle\DemoBundle\Entity\Task $task
     * @return $this
     */
    public function addTask(\Acme\Bundle\DemoBundle\Entity\Task $task)
    {
        $this->tasks[] = $task;

        return $this;
    }

    /**
     * @param \Acme\Bundle\DemoBundle\Entity\Task $task
     * @return $this
     */
    public function removeTask(\Acme\Bundle\DemoBundle\Entity\Task $task)
    {
        $this->tasks->remove($task);

        return $this;
    }

    /**
     * @return ArrayCollection
     */
    public function getTasks()
    {
        return $this->tasks;
    }

    /**
     * @param \Doctrine\Common\Collections\Collection $tasks
     * @return $this
     */
    public function setTasks(\Doctrine\Common\Collections\Collection $tasks)
    {
        $this->tasks = $tasks;

        return $this;
    }

    /**
     * @param \Knp\Component\Pager\Pagination\PaginationInterface $pagination
     * @return $this
     */
    public function setFromPagination(\Knp\Component\Pager\Pagination\PaginationInterface $pagination)
    {
        foreach ($pagination as $task) {
            $this->addTask($task);
        }

        return $this;
    }
}
Run Code Online (Sandbox Code Playgroud)

并在TaskListType类下面找到:

<?php

namespace Acme\Bundle\DemoBundle\Form;

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

class TaskListType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add(
                'tasks',
                'collection',
                array(
                    'type' => new \Acme\Bundle\DemoBundle\Form\TaskType(),
                )
            )
            ->add('save', 'submit');
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(
            array(
                'data_class' => 'Acme\Bundle\DemoBundle\Model\TaskList'
            )
        );
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'acme_demo_task_list';
    }
}
Run Code Online (Sandbox Code Playgroud)

和您的services.yml(可选):

services:
    acme.demo.form.type.task_list:
        class: Acme\Bundle\DemoBundle\Form\TaskListType
        tags:
            - { name: form.type, alias: acme_demo_task_list }
Run Code Online (Sandbox Code Playgroud)

和一个样本控制器:

public function indexAction($page)
{
    ini_set('xdebug.max_nesting_level', 300); // this might be useful with deeply nested forms

    $search = $this->getRequest()->get(
        'search',
        array(
            'name' => '',
            'date' => '',
            'lang' => $this->container->getParameter('acme_core.default_lang')
        )
    );

    /**
     * @var \Doctrine\ORM\EntityManager $em
     */
    $em = $this->getDoctrine()->getManager();

    $paginator = $this->get('knp_paginator');
    $pagination = $paginator->paginate(
        $em->getRepository('AcmeDemoBundle:Task')->getQueryFilteringByLangNameAndDate(
            $search['lang'],
            $search['name'],
            $search['date'] != '' ? new \DateTime($search['date']) : null
        ),
        $page,
        $this->getRequest()->get('elementsPerPage', 10)
    );

    $taskList = new TaskList();
    $taskList->setFromPagination($pagination);

    $form = $this->createForm('acme_demo_task_list', $taskList); // "acme_demo_task_list" has been defined in the services.yml file
    $form->handleRequest($this->getRequest());

    if ($form->isValid()) {
        foreach ($form->getData() as $task) {
            $em->merge($task);
        }
        $em->flush();
    }

    return $this->render(
        'AcmeDemoBundle:Task:index.html.twig',
        array(
            'search' => $search,
            'pagination' => $pagination,
            'form' => $form->createView()
        )
    );
}
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助!