用添加/删除方法Symfony2多文件上传 [英] Symfony2 multiple file upload with add / remove method
问题描述
我尝试将现有和正在使用的单个文件上传表单升级为具有添加和删除功能的多文件上传。因此,我用这个文件: http ://symfony.com/doc/current/cookbook/form/form_collections.html#allowing-new-tags-with-the-prototype
我的实体不叫标签,但是附件。
我可以通过Javascript添加无限的名字+文件字段。添加之后,我得到这个异常:
lockquote
FatalErrorException:错误:调用成员函数时在/应用程序中包含一个非对象/MAMP/htdocs/Seotool/src/Seotool/MainBundle/Entity/Attachments.php line 232
我也想,那不是全部在我的代码是正确的,而我试图升级到多个上传功能。也许有人可以帮助我解决所有问题?
这是我现在的代码,从我的控制器开始,他正在生成表单。 $ b
/ **
@Route(
* path =/ taskmanager / user / {user_id},
* name = taskmanager
*)
* @Template()
* /
public function taskManagerAction($ user_id,Request $ request)
{
/ * ####新任务#### * /
$任务=新任务();
$ attachment = new Attachments();
$ task-> getAttachments() - > add($ attachment);
$ addTaskForm = $ this-> createForm(new TaskType(),$ task);
$ addTaskForm-> handleRequest($ request);
$ b $ if($ addTaskForm-> isValid()):
/ *当前用户任务列表的用户对象* /
$ userid = $ this-> ; getDoctrine()
- > getRepository('SeotoolMainBundle:User')
- > find($ user_id);
$ task-> setDone(FALSE);
$ task-> setUser($ userid);
$ task-> setDateCreated(new \DateTime());
$ task-> setDateDone(NULL);
$ task-> setTaskDeleted(FALSE);
$ attachment-> setTask($ task);
$ attachment-> setUser($ userid);
$ attachment - > upload();
$ em = $ this-> getDoctrine() - > getManager();
$ em-> persist($ task);
$ em-> flush();
$ this-> log($ user_id,$ task-> getId(),'addTask');
$ b $ return $ this-> redirect($ this-> generateUrl('taskmanager',array('user_id'=> $ user_id)));
endif;
.....
这是我的任务的特定代码片段.php实体
<?php
名称空间Seotool \MainBundle \Entity;
使用Doctrine\Common\Collections\ArrayCollection;
使用Symfony \ Component \Vididator\Constraints as Assert;
使用Doctrine \ORM\Mapping作为ORM;
$ b / **
* @ ORM\Entity
* @ ORM\Table(name =tasks)
* /
class Task {
$ b $ ...
/ **
* @ ORM\OneToMany(targetEntity =Attachments,mappedBy =task,cascade = { persist})
* /
保护$附件;
...
/ **
*构造函数
* /
公共函数__construct()
{
$ this-> log = new \Doctrine\Common\Collections\ArrayCollection();
$ this-> attachments = new \Doctrine\Common\Collections\ArrayCollection();
...
/ **
*添加附件
*
* @param \Seotool \MainBundle\Entity\Attachments $附件
* @return任务
* /
公共函数addAttachment(\Seotool\MainBundle\Entity\Attachments $附件)
{
$ attachments-> addTask($ this);
$ this-> attachments-> add($ attachments);
$ b $ ** $ b $ *删除附件
*
* @param \Seotool\MainBundle\Entity\Attachments $附件
* /
public function removeAttachment(\Seotool\MainBundle\Entity\Attachments $ attachments)
{
$ this-> attachments-> removeElement($ attachments );
}
/ **
*获取附件
*
* @return \Doctrine\Common\Collections\Collection
* /
public function getAttachments()
{
return $ this-> attachments;
code $
这是我的Attachments.php实体
<?php
名称空间Seotool \MainBundle \Entity;
使用Doctrine\Common\Collections\ArrayCollection;
使用Symfony \ Component \HttpFoundation\File\UploadedFile;
使用Symfony \ Component \Vididator\Constraints as Assert;
使用Doctrine \ORM\Mapping作为ORM;
$ b / **
* @ ORM\Entity
* @ ORM\Table(name =attachments)
* /
class附件{
$ b / **
* @ ORM\Column(type =integer)
* @ ORM\Id
* @ ORM\GeneratedValue strategy =AUTO)
* /
保护$ id;
$ b / **
* @ ORM\Column(type =string,length = 255)
* @ Assert\NotBlank
* /
public $ name;
$ b $ ** b $ b * @ ORM\Column(type =string,length = 255,nullable = true)
* /
public $ path;
$ b / **
* @ ORM\ManyToOne(targetEntity =User,inversedBy =attachments)
* @ ORM\JoinColumn(name =user ,referencedColumnName =id)
* /
保护$用户;
$ b / **
* @ ORM\ManyToOne(targetEntity =Task,inversedBy =attachments)
* @ ORM\JoinColumn(name =task,referencedColumnName =id)
* /
protected $ task;
$ b / **
* @ Assert\File(maxSize =6000000)
* /
private $ file;
/ **
*设置文件。
*
* @param UploadedFile $ file
* /
public function setFile(UploadedFile $ file = null)
{
$ this-> file = $文件;
}
/ **
*获取文件。
*
* @return UploadedFile
* /
public function getFile()
{
return $ this-> file;
public function getAbsolutePath()
{
return null === $ this-> path
? null
:$ this-> getUploadRootDir()。'/'。$ this-> path;
public function getWebPath()
{
return null === $ this-> path
? null
:$ this-> getUploadDir()。'/'。$ this-> path;
$ b保护函数getUploadRootDir()
{
//上传的
文件的绝对目录路径
return __DIR __'/ .. / .. / .. / .. /网络/'.$这 - > getUploadDir();
}
保护函数getUploadDir()
{
//摆脱__DIR__所以它不会把
搞乱//显示上传doc / image在视图中。
返回上传;
$ b $ public function upload()
{
//如果字段不是必需的,file属性可以为空
if(null == = $ this-> getFile()){
return;
}
//在这里使用原始文件名,但你应该
//清理它至少以避免任何安全问题
//移动(
$ this-> getUploadRootDir(),$ b(
$ target),然后移动到
$ this-> getFile() - > move $ b $ this-> getFile() - > getClientOriginalName()
);
//将路径属性设置为您保存文件的文件名
$ this->路径= $ this-> getFile() - > getClientOriginalName();
//清理文件属性,因为不再需要它了
$ this-> file = null;
$ b / **
*获取id
*
* @return integer
* /
public function getId()
{
return $ this-> id;
$ b $ **
设定名称
*
* @参数字符串$名称
* @return附件
* /
public function setName($ name)
{
$ this-> name = $ name;
返回$ this;
$ b / **
*获取名称
*
* @return字符串
* /
public function getName )
{
return $ this-> name;
$ b $ **
*设置路径
*
* @param字符串$路径
* @return附件
* /
public function setPath($ path)
{
$ this-> path = $ path;
返回$ this;
$ b / **
*获取路径
*
* @return string
* /
public function getPath )
{
return $ this-> path;
$ b / **
*设置用户
*
* @param \Seotool\MainBundle\Entity\User $ user
* @return附件
* /
public function setUser(\Seotool\MainBundle\Entity\User $ user = null)
{
$ this- > User = $ user;
返回$ this;
$ b / **
*获取用户
*
* @return \Seotool\MainBundle\Entity\User
* /
public function getUser()
{
return $ this-> User;
$ b / **
*设置任务
*
* @param \Seotool\MainBundle\Entity\任务$任务
*返回附件
* /
public function setTask(\Seotool\MainBundle\Entity\Task $ task = null)
{
$ this-> task = $ task;
返回$ this;
}
/ **
*获取任务
*
* @return \Seotool\MainBundle\Entity\任务
* /
public function getTask()
{
return $ this-> task;
$ b $ public function addTask(Task $ task)
{
if(!$ this-> task-> contains($ task)){
$ this-> task-> add($ task);
$ b $ p $这是我的TaskType。 php表单类类:
<?php
名称空间Seotool \MainBundle\Form\Type;
使用Doctrine \ORM \EntityRepository;
使用Symfony \ Component\Form\AbstractType;
使用Symfony \ Component\Form\FormBuilderInterface;
使用Symfony \ Component\OptionsResolver\OptionsResolverInterface;
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $ builder,array $ options)
{
...
uilder-> add('attachments','collection',array(
'type'=> new AttachmentsType(),
'allow_add'=> true,
'allow_delete'=> true,
'delete_empty'=> true,
'by_reference'=> false,
));
这是我的AttachmentsType.php表单类:
<?php
namespace Seotool \MainBundle \Form\Type;
使用Doctrine \ORM \EntityRepository;
使用Symfony \ Component\Form\AbstractType;
使用Symfony \ Component\Form\FormBuilderInterface;
使用Symfony \ Component\OptionsResolver\OptionsResolverInterface;
class AttachmentsType extends AbstractType
{
public function buildForm(FormBuilderInterface $ builder,array $ options)
{
uilder-> add(' (
'label'=>'Dateiname',
'required'=> false,
));
uilder-> add('file','file',array(
'label'=> false,
'required'=> false,
attr=>数组(
multiple=>multiple,
)
));
public function setDefaultOptions(OptionsResolverInterface $ resolver)
{
$ resolver
- > setDefaults(array(
'data_class' =" Seotool\MainBundle\Entity\Attachments'
));
}
public function getName()
{
return'attachments';
$ / code $
解决方案问题是你添加你的附件时使用了错误的调用。
$ b $你的附件和任务之间的关联是一个 manyToOne
表示附件需要添加到任务
但是任务需要在附件上设置
。
要解决你的问题,你应该改变你的添加附件调用
public function addAttachment(\Seotool\MainBundle\Entity\Attachments $ attachments)
{
$ attachments-> addTask($ this);
//这个应该设置为不添加
$ this-> attachments-> add($ attachments);
$ / code>
到
<$ p
$ b $附件 - > setTask($ this); $ p $ public function addAttachment(\Seotool\MainBundle\Entity\Attachments $ attachment)
$ this-> attachments-> add($ attachment);
}
I tried to upgrade my existing and working single file upload form to a multi file upload with add and remove function. Therefor I used this docu: http://symfony.com/doc/current/cookbook/form/form_collections.html#allowing-new-tags-with-the-prototype
My Entity is not called tags but attachments.
I can add via Javascript unlimited name + file fields. After adding, I get this exception:
FatalErrorException: Error: Call to a member function contains() on a non-object in /Applications/MAMP/htdocs/Seotool/src/Seotool/MainBundle/Entity/Attachments.php line 232
I also think, that not all in my code is correct while I tried to upgrade to multiple upload function. Maybe someone can help me get all fixed?
That's my current code, starting with my controller, who is generating the form.
/**
@Route(
* path = "/taskmanager/user/{user_id}",
* name = "taskmanager"
* )
* @Template()
*/
public function taskManagerAction($user_id, Request $request)
{
/* #### NEW TASK #### */
$task = new Task();
$attachment = new Attachments();
$task->getAttachments()->add($attachment);
$addTaskForm = $this->createForm(new TaskType(), $task);
$addTaskForm->handleRequest($request);
if($addTaskForm->isValid()):
/* User Object of current Users task list */
$userid = $this->getDoctrine()
->getRepository('SeotoolMainBundle:User')
->find($user_id);
$task->setDone(FALSE);
$task->setUser($userid);
$task->setDateCreated(new \DateTime());
$task->setDateDone(NULL);
$task->setTaskDeleted(FALSE);
$attachment->setTask($task);
$attachment->setUser($userid);
$attachment->upload();
$em = $this->getDoctrine()->getManager();
$em->persist($task);
$em->flush();
$this->log($user_id, $task->getId(), 'addTask');
return $this->redirect($this->generateUrl('taskmanager', array('user_id' => $user_id)));
endif;
.....
This are particular code snippets of my Task.php Entity
<?php
namespace Seotool\MainBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="tasks")
*/
class Task {
....
/**
* @ORM\OneToMany(targetEntity="Attachments", mappedBy="task", cascade={"persist"})
*/
protected $attachments;
....
/**
* Constructor
*/
public function __construct()
{
$this->log = new \Doctrine\Common\Collections\ArrayCollection();
$this->attachments = new \Doctrine\Common\Collections\ArrayCollection();
}
....
/**
* Add attachments
*
* @param \Seotool\MainBundle\Entity\Attachments $attachments
* @return Task
*/
public function addAttachment(\Seotool\MainBundle\Entity\Attachments $attachments)
{
$attachments->addTask($this);
$this->attachments->add($attachments);
}
/**
* Remove attachments
*
* @param \Seotool\MainBundle\Entity\Attachments $attachments
*/
public function removeAttachment(\Seotool\MainBundle\Entity\Attachments $attachments)
{
$this->attachments->removeElement($attachments);
}
/**
* Get attachments
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getAttachments()
{
return $this->attachments;
}
This is my Attachments.php Entity
<?php
namespace Seotool\MainBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="attachments")
*/
class Attachments {
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank
*/
public $name;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
public $path;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="attachments")
* @ORM\JoinColumn(name="user", referencedColumnName="id")
*/
protected $User;
/**
* @ORM\ManyToOne(targetEntity="Task", inversedBy="attachments")
* @ORM\JoinColumn(name="task", referencedColumnName="id")
*/
protected $task;
/**
* @Assert\File(maxSize="6000000")
*/
private $file;
/**
* Sets file.
*
* @param UploadedFile $file
*/
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
}
/**
* Get file.
*
* @return UploadedFile
*/
public function getFile()
{
return $this->file;
}
public function getAbsolutePath()
{
return null === $this->path
? null
: $this->getUploadRootDir().'/'.$this->path;
}
public function getWebPath()
{
return null === $this->path
? null
: $this->getUploadDir().'/'.$this->path;
}
protected function getUploadRootDir()
{
// the absolute directory path where uploaded
// documents should be saved
return __DIR__.'/../../../../web/'.$this->getUploadDir();
}
protected function getUploadDir()
{
// get rid of the __DIR__ so it doesn't screw up
// when displaying uploaded doc/image in the view.
return 'uploads';
}
public function upload()
{
// the file property can be empty if the field is not required
if (null === $this->getFile()) {
return;
}
// use the original file name here but you should
// sanitize it at least to avoid any security issues
// move takes the target directory and then the
// target filename to move to
$this->getFile()->move(
$this->getUploadRootDir(),
$this->getFile()->getClientOriginalName()
);
// set the path property to the filename where you've saved the file
$this->path = $this->getFile()->getClientOriginalName();
// clean up the file property as you won't need it anymore
$this->file = null;
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return Attachments
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set path
*
* @param string $path
* @return Attachments
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* Get path
*
* @return string
*/
public function getPath()
{
return $this->path;
}
/**
* Set User
*
* @param \Seotool\MainBundle\Entity\User $user
* @return Attachments
*/
public function setUser(\Seotool\MainBundle\Entity\User $user = null)
{
$this->User = $user;
return $this;
}
/**
* Get User
*
* @return \Seotool\MainBundle\Entity\User
*/
public function getUser()
{
return $this->User;
}
/**
* Set Task
*
* @param \Seotool\MainBundle\Entity\Task $task
* @return Attachments
*/
public function setTask(\Seotool\MainBundle\Entity\Task $task = null)
{
$this->task = $task;
return $this;
}
/**
* Get Task
*
* @return \Seotool\MainBundle\Entity\Task
*/
public function getTask()
{
return $this->task;
}
public function addTask(Task $task)
{
if (!$this->task->contains($task)) {
$this->task->add($task);
}
}
}
This one is my TaskType.php Form Type Class:
<?php
namespace Seotool\MainBundle\Form\Type;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
....
$builder->add('attachments', 'collection', array(
'type' => new AttachmentsType(),
'allow_add' => true,
'allow_delete' => true,
'delete_empty' => true,
'by_reference' => false,
));
This is my AttachmentsType.php Form Type Class:
<?php
namespace Seotool\MainBundle\Form\Type;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class AttachmentsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', 'text', array(
'label' => 'Dateiname',
'required' => false,
));
$builder->add('file', 'file', array(
'label' => false,
'required' => false,
"attr" => array(
"multiple" => "multiple",
)
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver
->setDefaults(array(
'data_class' => 'Seotool\MainBundle\Entity\Attachments'
));
}
public function getName()
{
return 'attachments';
}
}
解决方案 Your problem is that you are using the wrong call when adding your attachment.
Your association between your attachment and task is a manyToOne
meaning that attachments needed to be added to a task
but a task needs to be set on an attachment
.
To sort out your problem your should just change your add attachment call from
public function addAttachment(\Seotool\MainBundle\Entity\Attachments $attachments)
{
$attachments->addTask($this);
// this should be set not add
$this->attachments->add($attachments);
}
to
public function addAttachment(\Seotool\MainBundle\Entity\Attachments $attachment)
{
$attachment->setTask($this);
$this->attachments->add($attachment);
}
这篇关于用添加/删除方法Symfony2多文件上传的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!