[英]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: 下一个是我的实体关系:
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.