Symfony维护文件上传的相对路径

时间:2019-01-13 21:07:30

标签: php symfony

我正在使用Symfony 4.1,但我很难让相对/全路径按我的意愿工作。

在我的数据库中,我有一个Customer实体,其属性称为photo。

<?php
namespace App\Entity;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;


/**
 * @ORM\Entity(repositoryClass="App\Entity\CustomerRepository")
 * @ORM\Table("Customer")
 */
class Customer {

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

     /**
       * @ORM\Column(type="string", nullable=true)
       *
       * @Assert\File(mimeTypes={ "image/png","image/jpeg" })
       */
     private $photo;

     public function getPhoto(): ?string
     {
        return $this->photo;
     }

     public function setPhoto(?string $photo): self
     {
        $this->photo = $photo;
        return $this;
     }

这很有道理,当我用上载照片的方式保存客户时,会按我的期望将照片保存在数据库和文件系统中。

在数据库中,“照片”列将设置为“ 010925c8c427bddca9020197212b64af.png”之类的

这就是我想要的,所以一切都很好。

当我尝试更新现有客户实体时出现问题。 Customer-> getPhoto()将返回相对路径文件名'010925c8c427bddca9020197212b64af.png。

但是该表单未通过验证,它表示此文件不存在。

$em = $this->getDoctrine()->getManager();
$custRepo = $em->getRepository('App:Customer');
$customer = $custRepo->findOneById($id);
$custForm = $this->createForm(CustomerType::class, $customer);
$custForm->handleRequest($request);
if ($custForm->isSubmitted() && $custForm->isValid()) {
    $em->flush();
}

它失败了,因为验证没有出现在photos目录中。

这是我的解决方案,它确实有效,但似乎过于骇客。我想知道是否有人对此有更优雅的方法。

$em = $this->getDoctrine()->getManager();
$custRepo = $em->getRepository('App:Customer');
$customer = $custRepo->findOneById($id);
$customer->setPhoto(new File($this->getParameter('photos_dir') .'/' . $customer->getPhoto()));
$custForm = $this->createForm(CustomerType::class, $customer);
$custForm->handleRequest($request);
if ($custForm->isSubmitted() && $custForm->isValid()) {
    $photoPathParts = explode('/', $customer->getPhoto());
    $customer->setPhoto(array_pop($photoPathParts));
    $em->flush();
}

我正在获取照片的完整路径并更新我当前正在处理的实体。这样就可以通过表单验证,但是如果我只保存它,数据库中的路径将更新为照片的完整路径。那不是我想要的,所以我将照片重置为相对路径文件名。

/**
 * @ORM\Column(type="string", nullable=true)
 *
 * @Assert\File(mimeTypes={ "image/png","image/jpeg" })
 */
 private $photo;

1 个答案:

答案 0 :(得分:1)

看这个例子如何上传图像。该图像位于单独的实体中,您可以将其与客户OneToOne相关。

<?php

namespace App\Entity;

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

/**
 * Image
 *
 * @ORM\Table(name="image")
 * @ORM\Entity(repositoryClass="App\Repository\ImageRepository")
 * @ORM\HasLifecycleCallbacks
 */
class Image
{
/**
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;
/**
 * @ORM\Column(name="extension", type="string", length=180)
 */

private $name;
/**
 * @Assert\Image()
 */
public $file;

private $tempFilename;

public function getId(): ?int
{
    return $this->id;
}

public function getName(): ?string
{
    return $this->name;
}

public function setName(string $name): self
{
    $this->name = $name;
    return $this;
}

public function setFile(UploadedFile $file)
{
    $this->file = $file;
    if (null !== $this->extension) {
        $this->tempFilename = $this->name;
        $this->extension = null;
        $this->name = null;
    }
}

public function getFile()
{
    return $this->file;
}

/**
 * @ORM\PrePersist()
 * @ORM\PreUpdate()
 */
public function preUpload()
{
    if (null === $this->file) {
        return;
    }
    $extension = $this->file->guessExtension();
    $this->name = md5(uniqid('', true)) . '.' . $extension;
}

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

/**
 * @ORM\PreRemove()
 */
public function preRemoveUpload()
{
    $this->tempFilename = $this->getUploadRootDir() . '/' . $this->name;
}

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

//folder
public function getUploadDir()
{
    return 'uploads/photos';
}

// path to folder web
protected function getUploadRootDir()
{
    return __DIR__ . '/../../public/' . $this->getUploadDir();
}

public function getWebPath()
{
    return $this->getUploadDir() . '/' . $this->getName();
}

}

ImageFormType

注意::您应该使用formType

中的公共属性$ file
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('file', FileType::class, array(
            'label'=> false,
        ))
    ;
}