Многократная загрузка файлов Symfony2 с использованием метода add / remove

Я попытался обновить существующую и рабочую единую файловую загрузку до многофайловой загрузки с добавлением и удалением функции. Поэтому я использовал этот документ: http://symfony.com/doc/current/cookbook/form/form_collections.html#allowing-new-tags-with-the-prototype

Моя сущность не называется тегами, а вложениями.

Я могу добавить через Javascript неограниченное имя + поля файла. После добавления я получаю это исключение:

FatalErrorException: Ошибка: вызов функции-члена содержит () для не-объекта в /Applications/MAMP/htdocs/Seotool/src/Seotool/MainBundle/Entity/Attachments.php строке 232

Я также думаю, что не все в моем коде правильные, когда я пытался обновить до нескольких функций загрузки. Может, кто-то может помочь мне все исправить?

Это мой текущий код, начиная с моего контроллера, который генерирует форму.

/** @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; ..... 

Это конкретные фрагменты кода моего объекта Task.php

 <?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; } 

Это мое приложение Attachments.php

 <?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); } } } 

Это мой тип TypeType.php Тип Тип:

 <?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, )); 

Это мой тип AttachmentsType.php Тип Тип:

 <?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'; } } 

Ваша проблема заключается в том, что вы используете неправильный вызов при добавлении вложения.

Ваша связь между вашим вложением и задачей – это manyToOne значение, означающее, что attachments needed to be added to a task но a task needs to be set on an attachment .

Чтобы решить проблему, нужно просто изменить свой добавочный вызов

 public function addAttachment(\Seotool\MainBundle\Entity\Attachments $attachments) { $attachments->addTask($this); // this should be set not add $this->attachments->add($attachments); } 

в

 public function addAttachment(\Seotool\MainBundle\Entity\Attachments $attachment) { $attachment->setTask($this); $this->attachments->add($attachment); }