填充多个表单 Symfony2

Populate Multiple Forms Symfony2

我有一个控制器,我正在其中创建一个未完成的作业列表并通过 Twig 在 table 中填充它们。 我现在想要的是每一行的最后一个字段是一个上传表单,这样您就可以将文件添加到一个特定的作业中。不幸的是,我不知道如何在一个控制器中处理多个表单的表单请求。

这是我现在拥有的控制器:

/**
 * @Route("/job/pending", name="pendingJobs")
 */
public function jobAction(Request $request)
{
    $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');

    $em = $this->getDoctrine()->getManager();
    $file = new File();
    $form = $this->createFormBuilder($file)
        ->add('file')
        ->add('job','entity',array(
            'class' => 'AppBundle:Job',
            'choice_label' => 'insuranceDamageNo',
        ))
        ->add('save', 'submit', array('label' => 'Create Task'))
        ->getForm();

    $form->handleRequest($request);

    if ($form->isValid()) {

        $job = $em->getRepository("AppBundle:Job")->find($form->getData()->getJob());

        $file->setFile($form->getData()->getFile());
        $file->setPath($form->getData()->getPath());
        $file->setJob($job);

        $em->persist($file);
        $em->flush();

        return $this->redirectToRoute("pendingJobs");
    }



    $jobs = $em->getRepository("AppBundle:Job")->findBy(array(
        'receipt' => true,
        'receiptStatus' => true,
    ));

    return $this->render(
        'default/pending.html.twig',
        array(
            'jobs' => $jobs,
            'form' => $form->createView(),
        )
    );


}

除了它只是一个表单并且 "Job" 实体是一个下拉列表之外,该表单工作完美。如果可能的话,我想 "pre-selected" 让每个工作都有正确的 ID。

我找到了一些关于 "createNamedBuilder" HERE (last post) but it is in french and neither do I understand french, nor does the API 的帮助。

我考虑过 $jobs 的 foreach,但如何分离表单句柄?

感谢任何提示!

我会用法语 post 逻辑和你的回答:

/**
 * @Route("/job/pending", name="pendingJobs")
 */
public function jobAction(Request $request)
{
    $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');

    $em = $this->getDoctrine()->getManager();
    $jobs = $em->getRepository("AppBundle:Job")->findBy(array(
        'receipt' => true,
        'receiptStatus' => true,
    ));

    foreach($jobs as $job) {


        $file = new File();
        $form = $this->get('form.factory')
                     ->createNameBuilder($job->getId(), new FileType(), $job)
                     ->getForm();


        $form->handleRequest($request);

        $forms[] = $form->createView();

        if ($form->isValid()) {

            $job = $em->getRepository("AppBundle:Job")->find($form->getName());

            $file->setFile($form->getData()->getFile());
            $file->setPath($form->getData()->getPath());
            $file->setJob($job);

            $em->persist($file);
            $em->flush();

            return $this->redirectToRoute("pendingJobs");
        }
    }

    return $this->render(
        'default/pending.html.twig',
        array(
            'jobs' => $jobs,
            'forms' => $forms,
        )
    );


}

为了更简洁,创建一个单独的 formType :

<?php
namespace AppBundle\Form\Type;

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

class FileType extends AbstractType
{
    public function getName()
    {
        return 'my_file_type';
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
     $builder
        ->add('file')
        ->add('job','entity',array(
            'class' => 'AppBundle:Job',
            'choice_label' => 'insuranceDamageNo',
        ))
        ->add('save', 'submit', array('label' => 'Create Task'))
    }
}

在您的控制器中创建三个动作。一个用于主页,一个用于每个上传表单,一个用于处理表单:

/**
 * @Route("/job", name="pendingJobs")
 */
public function jobAction(Request $request) {
    $em = $this->getDoctrine()->getManager();

    $jobs = $em->getRepository("AppBundle:Job")->findAll();

    return $this->render(
                'default/pending.html.twig', array(
                'jobs' => $jobs,
            )
    );
}

/*
 * renders an uploadform as a partial from jobAction
 */
public function jobrowAction(Request $request, Job $job) {
    //$this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');

    $em = $this->getDoctrine()->getManager();

    $file = new File();
    $file->setJob($job); // so that we know to what job this upload belongs!

    $form = $this->createUploadForm($file, $job->getId());

    return $this->render(
                'default/pending_job_row.html.twig', array(
                'job' => $job,
                'form' => $form->createView(),
            )
    );
}

/*
 * renders and processes an uploadform
 * 
 * @Route("/job/{id}/update", name="job_upload")
 * @Method("POST")
 */
public function uploadAction(Request $request, $id) {
    $em = $this->getDoctrine()->getManager();

    $file = new File();

    // this time we set the job property again cause we only receiced the jobId from the route
    $job = $em->getRepository("AppBundle:Job")->findOneBy(array('id' => $id));
    if (!$job) {
        throw $this->createNotFoundException('Unable to find Job entity.');
    }
    $file->setJob($job);

    $form = $this->createUploadForm($file, $id);
    $form->handleRequest($request);

    if ($form->isValid()) {

        $job = $em->getRepository("AppBundle:Job")->find($form->getData()->getJob());

        $file->setFile($form->getData()->getFile());
        $file->setPath($form->getData()->getPath());
        $file->setJob($job);

        $em->persist($file);
        $em->flush();

        return $this->redirectToRoute("pendingJobs");
    }

    // if the form is not valid show the form again with errors
    return $this->render(
                'default/error.html.twig', array(
                'form' => $form->createView(),
            )
    );
}

private function createUploadForm(File $file, $jobId)
{
    $form = $this->createFormBuilder($file, array(
                'action' => $this->generateUrl('job_upload', array('id' => $jobId)),
                'method' => 'POST',
            ))
            ->add('file')
            ->add('save', 'submit', array('label' => 'Create Task'))
            ->getForm();

    return $form;
}

然后制作两个Twig文件:

{# default/pending.html.twig #}

{% extends 'base.html.twig' %}

{% block body %}
    <table>
        {% for job in jobs %}
            <tr>
                <td>{{ job.title }}</td>
                <td>{{ render(controller('AppBundle:Default:jobrow', { 'job': job })) }}</td>
            </tr>
        {% endfor %}
    </table>
{% endblock %}

和:

{# default/pending_job_row.html.twig #}

{{ form(form) }}

在您的文件实体中缺少两个方法:

/**
 * Set job
 *
 * @param \AppBundle\Entity\Job $job
 *
 * @return File
 */
public function setJob(\AppBundle\Entity\Job $job = null)
{
    $this->job = $job;

    return $this;
}

/**
 * Get job
 *
 * @return \AppBundle\Entity\Job
 */
public function getJob()
{
    return $this->job;
}