填充多个表单 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;
}
我有一个控制器,我正在其中创建一个未完成的作业列表并通过 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;
}