我正在尝试通过表单上传多个文件,但我一次只能上传一个文件,这是我在浏览器中标记的最后一个文件。有没有办法使用简单的表单使用Symfony2上传更多图像? 这是我用来标记多个文件的表格的树枝模板:
{{ form_widget(form.post_image, { 'attr': {'multiple': 'multiple' }}) }}
答案 0 :(得分:12)
Ok解决绑定问题(enctype语法错误):我会给你我使用的代码。也许它会有所帮助...
我有图库实体
class Gallery
{
protected $id;
protected $name;
protected $description;
private $urlName;
public $files; // the array which will contain the array of Uploadedfiles
// GETTERS & SETTERS ...
public function getFiles() {
return $this->files;
}
public function setFiles(array $files) {
$this->files = $files;
}
public function __construct() {
$files = array();
}
}
我有一个生成表单
的表单类class Create extends AbstractType {
public function buildForm(FormBuilder $builder, array $options) {
$builder->add('name','text',array(
"label" => "Name",
"required" => TRUE,
));
$builder->add('description','textarea',array(
"label" => "Description",
"required" => FALSE,
));
$builder->add('files','file',array(
"label" => "Fichiers",
"required" => FALSE,
"attr" => array(
"accept" => "image/*",
"multiple" => "multiple",
)
));
}
}
现在位于控制器
class GalleryController extends Controller
{
public function createAction() {
$gallery = new Gallery();
$form = $this->createForm(new Create(), $gallery);
// Altering the input field name attribute
$formView = $form->createView();
$formView->getChild('files')->set('full_name', 'create[files][]');
$request = $this->getRequest();
if($request->getMethod() == "POST")
{
$form->bindRequest($request);
// print "<pre>".print_r($gallery->getFiles(),1)."</pre>";
if($form->isValid())
{
// Do what you want with your files
$this->get('gallery_manager')->save($gallery);
return $this->redirect($this->generateUrl("_gallery_overview"));
}
}
return $this->render("GalleryBundle:Admin:create.html.twig", array("form" => $formView));
}
}
希望这有帮助...
注意:如果有人知道改变这个f * * 名称属性的更好方法,可能在FormView类中或通过声明新的字段类型,请随时向我们展示您的方法......
答案 1 :(得分:12)
不需要额外的课程(除了gallery_manger服务,但你描述的问题发生在......之前)
我真的不知道出了什么问题。检查您的模板(可能是错误的enctype ...或名称attr mismatching)
首先尝试单个文件上传,查看文档:
一旦有效,你必须编辑一些行。
将代码复制/粘贴到此处。
答案 2 :(得分:7)
我在这里找到的所有建议都是针对实际情况的解决方法。
为了能够拥有多个附件,您应该使用表单集合。
来自文档的引用:
在此条目中,您将学习如何创建嵌入许多其他表单集合的表单。这可能很有用,例如,如果您有一个Task类,并且想要在同一个表单内编辑/创建/删除与该任务相关的许多Tag对象。
http://symfony.com/doc/2.0/cookbook/form/form_collections.html
示例案例:您有一个文档,该文档由DocumentType指定。该文档必须具有多个附件,您可以通过定义AttachmentType表单并将其作为集合添加到DocumentType表单来实现。
答案 3 :(得分:4)
对于sf&gt; 2.2: 在表单类型类中,添加此重写方法:
public function finishView(FormView $view, FormInterface $form, array $options) {
$view->vars['form']->children['files']->vars['full_name'] .= '[]';
}
答案 4 :(得分:3)
使用此方法:
$form = $this->createFormBuilder()
->add('attachments','file', array('required' => true,"attr" => array(
"multiple" => "multiple",
)))
->add('save', 'submit', array(
'attr' => array('class' => 'btn btn-primary btn-block btn-lg'),
'label' => 'save'
))
->getForm();
然后通过jQuery将[]添加到输入的名称:
<input id="form_attachments" name="form[attachments]" required="required" multiple="multiple" type="file">
jQuery代码:
<script>
$(document).ready(function() {
$('#form_attachments').attr('name',$('#form_attachments').attr('name')+"[]");
});
</script>
答案 5 :(得分:2)
您需要更改需要映射数组的输入文件名属性。
<input type="file" name="name[]" multiple />
答案 6 :(得分:2)
请注意,我尝试使用以下语法在sf2中执行相同的操作:
在控制器中:
public function stuffAction() {
$form = $this->createFormBuilder()
->add('files','file',array(
"attr" => array(
"accept" => "image/*",
"multiple" => "multiple",
)
))
->getForm();
$formView = $form->createView();
$formView->getChild('files')->set('full_name', 'form[files][]');
// name param (eg 'form[files][]') need to be the generated name followed by []
// try doing this : $formView->getChild('files')->get('full_name') . '[]'
$request = $this->getRequest();
if($request->getMethod() == "POST") {
$form->bindRequest($request);
$data = $form->getData();
$files = $data["files"];
// do stuff with your files
}
}
return $this->render('Bundle:Dir:index.html.twig',array("form" => $formView));
}
$files
将是一系列已上传的文件......
调用$form->createView()
来改变name属性当然不是最好的方法/最干净的方法,但它是我发现的唯一一个保持csrf功能正常工作的方法,因为改变了树枝模板中的name属性使得它无效......
现在我仍然有一个问题,使用生成表单的表单类,我不知道为什么在绑定表单数据和&amp;附加到表单的对象我的上传文件数组转换为(文件)名称???
的数组答案 7 :(得分:2)
以上是上传多个文件的简单示例。我上传文件有类似的问题。
https://github.com/marekz/example_symfony_multiply_files_example
对于symfony 3。*
首先:两者都形成声明:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use AppBundle\Form\FilesType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
class UserType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('lastName')
->add('files', CollectionType::class,array(
'entry_type' => FilesType::class,
'allow_add' => true,
'by_reference' => false,
))
;
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\User'
));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_user';
}
}
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class FilesType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('file');
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Files'
));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_files';
}
}
现在,我的实体:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* User
*
* @ORM\Table(name="user")
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User {
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* @var string
*
* @ORM\Column(name="lastName", type="string", length=255)
*/
private $lastName;
/**
* @ORM\ManyToMany(targetEntity="Files", cascade={"persist"})
*/
private $files;
function __construct() {
$this->files = new ArrayCollection();
}
/**
* Get id
*
* @return int
*/
public function getId() {
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return User
*/
public function setName($name) {
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName() {
return $this->name;
}
/**
* Set lastName
*
* @param string $lastName
*
* @return User
*/
public function setLastName($lastName) {
$this->lastName = $lastName;
return $this;
}
/**
* Get lastName
*
* @return string
*/
public function getLastName() {
return $this->lastName;
}
/**
* Get files
*
* @return ArrayCollection
*/
function getFiles() {
return $this->files;
}
/**
* Set files
* @param type $files
*/
function setFiles($files) {
$this->files = $files;
}
}
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Files
*
* @ORM\Table(name="files")
* @ORM\Entity(repositoryClass="AppBundle\Repository\FilesRepository")
*/
class Files
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="file", type="string", length=255, unique=true)
* @Assert\NotBlank(message="Please, upload the product brochure as a PDF file.")
* @Assert\File(mimeTypes={ "application/pdf" })
*/
private $file;
/**
*
* @return Files
*/
function getUser() {
return $this->user;
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set file
*
* @param string $file
*
* @return Files
*/
public function setFile($file)
{
$this->file = $file;
return $this;
}
/**
* Get file
*
* @return string
*/
public function getFile()
{
return $this->file;
}
}
Finaly,Symfony Controller:
/**
* Creates a new user entity.
*
* @Route("/new", name="user_new")
* @Method({"GET", "POST"})
*/
public function newAction(Request $request) {
$user = new User();
$form = $this->createForm('AppBundle\Form\UserType', $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$attachments = $user->getFiles();
if ($attachments) {
foreach($attachments as $attachment)
{
$file = $attachment->getFile();
var_dump($attachment);
$filename = md5(uniqid()) . '.' .$file->guessExtension();
$file->move(
$this->getParameter('upload_path'), $filename
);
var_dump($filename);
$attachment->setFile($filename);
}
}
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return $this->redirectToRoute('user_show', array('id' => $user->getId()));
}
return $this->render('user/new.html.twig', array(
'user' => $user,
'form' => $form->createView(),
));
}
答案 8 :(得分:1)
2.3中删除了getChild
和set()
方法。
除此之外,您应该使用children[]
和vars
属性
之前:
$formView->getChild('files')->set('full_name', 'form[files][]');
后:
$formView->children['files']->vars = array_replace($formView->children['files']->vars, array('full_name', 'form[files][]'));
答案 9 :(得分:1)
Symfony在symfony 2.5中为文件字段类型引入了'multiple'选项
$builder->add('file', 'file', array('multiple' => TRUE));
答案 10 :(得分:0)
如果会出现一些验证错误会怎样?将Symfony表重新发布多个文件上传字段。因为我尝试了它,我认为为此目的,您需要使用文件字段的集合。比symfony表单必须正确渲染所有字段。