简体   繁体   English

Symfony2-上传文件(编辑表单)

[英]Symfony2 - Upload File (Edit form)

My problem is, when I upload a file with a edit form, if entity's field is empty, the file upload perfectly, but, if the entity's field is not empty (previously I've uploaded a file), the field that reference the file uploaded is not updated and the file is not uploaded. 我的问题是,当我使用编辑表单上传文件时,如果实体的字段为空,则文件完美上传,但是,如果实体的字段不为空(以前我已上传文件),则引用该文件的字段上传没有更新,文件也没有上传。

My entity relationship is the next: 下一个是我的实体关系:

  • Class Documents => Table where the names and paths are stored. 类文档=>表,用于存储名称和路径。
  • Class MyEntity (any with edit action) => Entitys with a int field that reference Documents.id 类MyEntity(任何具有编辑操作的实体)=>具有引用Documents.id的int字段的实体

MyEntityController.php MyEntityController.php

public function editTeamAction($comp, $id) {
    if(!$id)
        throw $this->createNotFoundException('ID is needed, '. $id);
    $em = $this->getDoctrine()->getEntityManager();
    $entity = $em->getRepository('MyBundle:MyEntity')->find($id);
    if(!$entity)
        throw $this->createNotFoundException('Entity not found with id '. $id);
    $editForm = $this->createEditForm($entity);

    return $this->render("MyBundle::edit.html.twig", array("entity"=> $entity, "comp" => $comp, "edit_form"=>$editForm->createView(), "path_form" => "ent_update"));
}

private function createEditForm(MyEntity $entity) {
    $form = $this->createForm(new MyEntityType(), $entity);
    $form->add('submit', 'submit', array('label' => 'Update'));

    return $form;
}

public function updateTeamAction(Request $request, $comp, $id) {
    $em = $this->getDoctrine()->getEntityManager();
    $entity = $em->getRepository('MyBundle:MyEntity')->find($id);
    if(!$entity)
        throw $this->createNotFoundException('Entity not found with id '. $id);

    $editForm = $this->createEditForm($entity);
    $editForm->handleRequest($request);

    if($editForm->isValid())
    {
        $em->persist($entity);
        $em->flush();

        $this->get('session')->getFlashBag()->add(
            'notice',
            'Edit success.'
        );
        return $this->redirect($this->generateUrl('ent_edit', array('comp' => $comp, 'id' => $id)));
    }
    return $this->render("MyBundle::edit.html.twig", array("entity"=> $entity, "comp" => $comp, "edit_form"=>$editForm->createView(), "path_form" => "ent_update"));
}

MyEntity.php MyEntity.php

namespace My\Bundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use My\Bundle\Entity\Documents;

/**
 * MyEntity
 *
 * @ORM\Table()
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 */
class MyEntity
{
    /**
     * @var integer
     *
     * @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;

    /**
     * @ORM\ManyToOne(targetEntity="Comp", inversedBy="myentity")
     * @ORM\JoinColumn(name="comp_id", referencedColumnName="id")
     */
    protected $Comp;

    /**
     * @var string
     *
     * @ORM\Column(name="web", type="string", length=255, nullable=true)
     */
    private $web;

    /**
     * @ORM\ManyToOne(targetEntity="Documents", cascade={"persist", "remove"}, inversedBy="myentity")
     * @ORM\JoinColumn(name="logo", referencedColumnName="id", nullable=true)
     */
    private $logo = null;

    /**
     * @ORM\Column(type="datetime")
     *
     * @var \DateTime
     */
    private $updatedAt;

    /**
     * @ORM\ManyToOne(targetEntity="Documents", inversedBy="myentity")
     * @ORM\JoinColumn(name="images", referencedColumnName="id", nullable=true)
     */
    protected $images = null;

    public function __construct()
    {
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return MyEntity
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set comp
     *
     * @param \My\Bundle\Entity\Comp $comp
     * @return MyEntity
     */
    public function setComp(\My\Bundle\Entity\Comp $comp = null)
    {
        $this->comp = $comp;

        return $this;
    }

    /**
     * Get comp
     *
     * @return \My\Bundle\Entity\Comp 
     */
    public function getCompeticion()
    {
        return $this->competicion;
    }

    /**
     * Set web
     *
     * @param string $web
     * @return MyEntity
     */
    public function setWeb($web)
    {
        $this->web = $web;

        return $this;
    }

    /**
     * Get web
     *
     * @return string 
     */
    public function getWeb()
    {
        return $this->web;
    }

    /**
     * Set images
     *
     * @param \My\Bundle\Entity\Documents $images
     * @return MyEntity
     */
    public function setImages(\My\Bundle\Entity\Documents $images = null)
    {
        $this->images = $images;

        return $this;
    }

    /**
     * Get images
     *
     * @return \My\Bundle\Entity\Documents 
     */
    public function getImages()
    {
        return $this->images;
    }

    /**
     * Set updatedAt
     *
     * @param \DateTime $updatedAt
     * @return MyEntity
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    /**
     * Get updatedAt
     *
     * @return \DateTime 
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }

    /**
     * Set logo
     *
     * @param \My\Bundle\Entity\Documents $logo
     * @return MyEntity
     */
    public function setLogo(\My\Bundle\Entity\Documents $logo = null)
    {
        $this->logo = $logo;

        return $this;
    }

    /**
     * Get logo
     *
     * @return \My\Bundle\Entity\Documents 
     */
    public function getLogo()
    {
        return $this->logo;
    }
}

Documents.php Documents.php

namespace My\Bundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\File\File;

/**
 * Documents
 *
 * @ORM\Table()
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 */
class Documents
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     * @Assert\NotBlank
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="path", type="string", length=255)
     */
    private $path;

    public $file;

    /**
     * @ORM\OneToMany(targetEntity="MyEntity", mappedBy="images")
     */
    protected $myentity;

    public function __construct($path = "")
    {
        $this->myentity = new \Doctrine\Common\Collections\ArrayCollection();
        $this->setPath($path);
    }

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate()
     */
    public function preUpload()
    {
        $this->tempFile = $this->getAbsolutePath();
        $this->oldFile = $this->getPath();
        if(null !== $this->file)
        {
            $filename = sha1(uniqid(mt_rand(), true));
            $this->name = $filename.'.'.$this->file->guessExtension();
        }
    }

    /**
     * @ORM\PostPersist()
     * @ORM\PostUpdate()
     */
    public function upload()
    {
        if (null === $this->file)
            return;
        $this->preUpload($this->file);
        if(null !== $this->file)
        {
            $this->file->move($this->getUploadRootDir().$this->path, $this->name);
            unset($this->file);

            //if($this->oldFile != null)
            //     unlink($this->tempFile);    
        }
    }

    /**
     *  @ORM\PostLoad()
     */
    public function postLoad()
    {
        $this->updatedAt = new \DateTime('now');
    }

    /**
     * @ORM\PreRemove()
     */
    public function preRemoveUpload()
    {
        $this->tempFile = $this->getAbsolutePath();
    }

    /**
     * @ORM\PostRemove()
     */
    public function removeUpload()
    {
        // if($file = $this->getAbsolutePath())
        //     unlink($file);
        if(file_exists($this->tempFile))
            unlink($this->tempFile);
    }

    public function getWebPath()
    {
        return null === $this->path
            ? null
            : $this->getUploadDir().'/'.$this->path;
    }

    public function getAssetPath()
    {
        return $this->getUploadDir().$this->path;
    }

    /**
     * Called after entity persistence
     *
     * @ORM\PostPersist()
     * @ORM\PostUpdate()
     */

    protected function getUploadRootDir()
    {
        // the absolute directory path where uploaded
        // documents should be saved
        return __DIR__.'/../../../../web/'.$this->getUploadDir();
    }

    public function getAbsolutePath()
    {
        return null === $this->path ? null : $this->getUploadRootDir().$this->path;
    }

    protected function getUploadDir()
    {
        // get rid of the __DIR__ so it doesn't screw up
        // when displaying uploaded doc/image in the view.
        return 'uploads/';
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Documents
     */
    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 Documents
     */
    public function setPath($path)
    {
        $this->path = $path;

        return $this;
    }

    /**
     * Get path
     *
     * @return string 
     */
    public function getPath()
    {
        return $this->path;
    }

    /**
     * Add myentity
     *
     * @param \My\Bundle\Entity\MyEntity $myentity
     * @return Documents
     */
    public function addMyentity(\My\Bundle\Entity\MyEntity $myentity)
    {
        $this->myentity[] = $myentity;

        return $this;
    }

    /**
     * Remove myentity
     *
     * @param \My\Bundle\Entity\MyEntity $myentity
     */
    public function removeMyentity(\My\Bundle\Entity\MyEntity $myentity)
    {
        $this->myentity->removeElement($myentity);
    }

    /**
     * Get myentity
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getMyentity()
    {
        return $this->myentity;
    }

    /**
     * @return File
     */
    public function getFile()
    {
        return $this->file;
    }
}

MyEntityType.php MyEntityType.php

namespace My\Bundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Doctrine\ORM\EntityRepository;

class MyEntityType extends AbstractType
{
    public function __construct()
    {
    }
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('comp', "entity", array(
                "label"=>"Comp", 
                "class" => "MyBundle:Comp",
                "property" => "nameEn",
                "query_builder" => function(EntityRepository $er) {
                    return $er->createQueryBuilder("c")
                        ->orderBy("c.nameEn", "ASC");
                }))
            ->add('name', 'text')
            ->add('country', "entity", array(
                "label"=>"Country", 
                "class" => "CountryBundle:Country",
                "property" => "englishName",
                "query_builder" => function(EntityRepository $er) {
                    return $er->createQueryBuilder("p")
                        ->orderBy("p.englishName", "ASC");
                }))
            ->add('web', 'text', array("required" => false, "render_optional_text" => false))
            ->add('logo', new DocumentsType('logo_entity'), array('horizontal' => false, 'label' => 'Logo'))
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'My\Bundle\Entity\MyEntity'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return '';
    }
}

DocumentsType.php DocumentsType.php

namespace My\Bundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class DocumentsType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('file', 'file', array('required' => false, 'label' => false))
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'My\Bundle\Entity\Documents'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'documents';
    }
}

edit.html.twig edit.html.twig

{% extends 'MyBundle::base.html.twig' %}

{% block stylesheets %}
    {{ parent() }}
{% endblock %}
{% block javascripts %}
    {{parent()}}
{% endblock %}
{% block wrapper %}
    {{parent()}}
    <h3>Edit</h3>
    {% for flashMessage in app.session.flashbag.get('notice') %}
        {{ flashMessage }}
    {% endfor %}
    <form action="{{ path(path_form, { 'id': entity.id, 'comp' : comp }) }}" method="POST" {{ form_enctype(edit_form) }}>
        {{ form(edit_form) }}
    </form>
{% endblock %}

Hi think that the problem is in your Controller (MyEntityController.php) 您好,认为问题出在您的控制器(MyEntityController.php)中
After the form validation, in updateTeamAction you are using this: 表单验证之后,在updateTeamAction中,您将使用以下代码:

    if($editForm->isValid())
{
    $em->persist($entity);
    $em->flush();

    $this->get('session')->getFlashBag()->add(
        'notice',
        'Edit success.'
    );
    return $this->redirect($this->generateUrl('ent_edit', array('comp' => $comp, 'id' => $id)));
}  

But in this way you are persisting the $entity, and not updated one. 但是通过这种方式,您将保留$ entity,而不更新它。 you need to get the entity from the form in this way: 您需要通过以下方式从表单中获取实体:

    if($editForm->isValid())
{
    $em->persist($editForm->getData());
    $em->flush();

    $this->get('session')->getFlashBag()->add(
        'notice',
        'Edit success.'
    );
    return $this->redirect($this->generateUrl('ent_edit', array('comp' => $comp, 'id' => $id)));
}  

Try this way and give us your feedback 尝试这种方式,并给我们您的反馈意见

Well, I found (finally!) the solution for this problem. 好吧,我找到了(最后!)解决该问题的方法。

The UpdateAction from Controller has to check that if the form is sent a new file. Controller的UpdateAction必须检查是否向表单发送了新文件。 If not, the entity has to setLogo (in my case) the actual logo that has in DB. 如果不是,则实体必须设置setLogo(在我的情况下)是数据库中的实际徽标。 If a new file exists and is valid, I create a new Documents object, and set the File with the file uploaded. 如果存在一个新文件并且有效,那么我将创建一个新的Documents对象,并使用已上传的文件设置File。 Finally, I remove the previous logo from the server (this is optional). 最后,我从服务器上删除了以前的徽标(这是可选的)。

The code's updateAction: 代码的updateAction:

MyEntityController.php MyEntityController.php

public function updateTeamAction(Request $request, $comp, $id) {
    $em = $this->getDoctrine()->getEntityManager();
    $entity = $em->getRepository('MyBundle:MyEntity')->find($id);
    if(!$entity)
        throw $this->createNotFoundException('Entity not found with id '. $id);

    $editForm = $this->createEditForm($entity);
    //Save original Logo
    $logoOriginal = $entity->getLogo();
    $editForm->handleRequest($request);
    if($editForm->isValid())
    {
        $files = $request->files;
        $uploadedFile = $files->get('logo')['file'];
        if(count($uploadedFile)==0)
            $entity->setLogo($logoOriginal);
        else
        {
            $documents = new Documents();
            $documents->setPath('logo');
            $documents->setFile($uploadedFile);

            $entity->setLogo($documents);
            if(!empty($logoOriginal))
            {
                $fs = new Filesystem();
                $fs->remove($documents->getAbsolutePath().'/'.$logoOriginal->getName());
            }
        }
        $em->persist($entity);
        $em->flush();
        $this->get('session')->getFlashBag()->add(
            'notice',
            'Edit success.'
        );
        return $this->redirect($this->generateUrl('ent_edit', array('comp' => $comp, 'id' => $id)));
    }
    return $this->render("MyBundle::edit.html.twig", array("entity"=> $entity, "comp" => $comp, "edit_form"=>$editForm->createView(), "path_form" => "ent_update"));
}

If you want the step to remove, add to controller this: 如果要删除该步骤,请向控制器添加以下内容:

use Symfony\Component\Filesystem\Filesystem;

In the end, I realized I had a problem with the name of the new file created (was not the same that was stored in the DB that was created in the server folder). 最后,我意识到我创建的新文件的名称存在问题(与服务器文件夹中创建的数据库中存储的文件不同)。 In Documents entity, I modified the upload() function, removing this line 在Documents实体中,我修改了upload()函数,删除了这一行

$this->preUpload($this->file); $这个 - > preUpload($这个 - >文件);

So, the final code of upload() function is the next: 因此,下一个upload()函数的最终代码是:

Documents.php Documents.php

/**
 * @ORM\PostPersist()
 * @ORM\PostUpdate()
 */
public function upload()
{
    if (null === $this->file)
        return;
    if(null !== $this->file)
    {
        $this->file->move($this->getUploadRootDir().$this->path, $this->name);
        unset($this->file);
        //if($this->oldFile != null)
        //     unlink($this->tempFile);    
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM