Php Symfony2使用添加/删除方法进行多文件上载

Php Symfony2使用添加/删除方法进行多文件上载,php,forms,symfony,templates,file-upload,Php,Forms,Symfony,Templates,File Upload,我尝试将我现有的和正在工作的单文件上传表单升级为具有添加和删除功能的多文件上传。因此,我使用了以下文件: 我的实体不是标签,而是附件 我可以通过Javascript添加无限的名称+文件字段。添加后,我得到以下异常: FatalErrorException:错误:在/Applications/MAMP/htdocs/Seotool/src/Seotool/MainBundle/Entity/Attachments.php第232行对非对象调用成员函数contains() 我还认为,当我试图升级到多

我尝试将我现有的和正在工作的单文件上传表单升级为具有添加和删除功能的多文件上传。因此,我使用了以下文件:

我的实体不是标签,而是附件

我可以通过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;
}
<?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);
    }
}
}

您的问题是在添加附件时使用了错误的呼叫

附件和任务之间的关联是一个
manytone
,这意味着需要将
附件添加到任务中
,但
任务需要在附件中设置

要解决您的问题,您只需将添加附件呼叫从

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

    $this->attachments->add($attachments);
}


好了,例外情况消失了。当添加带有2个附件的新任务时(其中一个带有“添加”按钮,这样我就有2个字段可以上传附件),第一个附件只会放入我的数据库中。你知道为什么吗?因为你只上传了一个文件。您需要循环查看添加的附件(可能通过
$form->get('attachments')
)并执行任务(
setTask,
setUser
upload`)。。。。我想,这不是由Symfony做的吗?我从来没有看到过任何代码片段带有循环来保存多个文件:-/据我所知,Symfony实际上并不处理多个文件上传。我看到的多文件上传使用某种javascript小部件单独发送每个文件,这将使用与上面相同的过程。不过我可能错了。如果你能找到一些教程说,否则,我会看看,并试图回答相应的。也许你有时间聊天?这比用评论交流更容易
<?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';
}
}
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);
}