使用添加/删除方法上传Symfony2多文件

时间:2014-09-01 20:02:15

标签: php forms symfony templates file-upload

我尝试将现有的和正在运行的单个文件上传表单升级为具有添加和删除功能的多文件上载。因此我使用了这个文档: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行中的非对象上调用成员函数contains()

我也认为,当我尝试升级到多个上传功能时,并非所有代码都正确。也许有人可以帮我解决所有问题?

这是我当前的代码,从我的控制器开始,正在生成表单。

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

这是我的TaskType.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';
}
}

1 个答案:

答案 0 :(得分:1)

您的问题是在添加附件时使用了错误的电话。

您的附件和任务之间的关联为manyToOne,表示attachments needed to be added to a taska 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);
}