在单个表Symfony中处理filesUpload

问题描述 投票:-1回答:1

感谢您的关注,

SHORT

我想在单个实体中管理我的所有上传(图像,PDF,视频等...),因此我使用实体继承来获取各种“类型”和OneToOne关系以将父实体与正确的上载链接起来。我没有找到任何捆绑来做这件事并面临问题:

  • 约束使用
  • 设置上传文件而不上传实体
  • 获取上传文件而不上传实体(版本)

LONG

而不是在每个表中有一个文件管理(这是安静的详细)我更喜欢只有一个表Uploads来处理每个上传。然后我只需要做OneToOne关系来获取我的文件,加上使用继承我可以根据ImagePDF应用各种处理。

我至少有4个需要图像的实体,所以我认为1to1关系是一个不错的选择。

但我在做这样的事情时遇到了问题:

  • Constraints没有考虑到
  • $file的版本应该设置$file->file(它不会从Uploads / Image发送实体,而是创建此实体的文件
  • 上载的文件未在实体版本上加载,每次编辑实体时都应重新上载

有没有人这样做过?我无法找到如何正确实现这一目标。

看看断言问题,我试图:

  • Image上定义断言(这不像预期的那样工作,因为$fileWithImage形式目标) 使用注释@Assert\Image() 使用loadValidatorMetadata 使用注释@Assert\Callback()
  • 在表单字段'constraints' => array(new Assert\Image())上定义断言,这可行,但需要在我使用它的任何地方定义...

看着被误用的二传手我找到了一个解决方法,但这很安静丑陋:

public function setFile($file = null)
{
    if ($file instanceof \Symfony\Component\HttpFoundation\File\UploadedFile) {
        $tmpfile = new Image();
        $tmpfile->setFile($file);
        $file = $tmpfile;
    }
    $this->file = $file;

    return $this;
}

(PS:我读过关于避免复制/粘贴代码的特性,我已经检查了SonataMediaBundle但这似乎不适用于我的情况)

CODE

所以我设计了我的课程如下:

Entity \ Uploads.php处理从上传到删除文件的所有生命(以及访问,移动,编辑,可能缩略图等...)

<?php

namespace Acme\CoreBundle\Entity;

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

use Acme\CoreBundle\Utils\UUID;

/**
 * Uploads
 *
 * @ORM\Table(name="uploads")
 * @ORM\Entity(repositoryClass="Acme\CoreBundle\Repository\UploadsRepository")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="class", type="string")
 * @ORM\DiscriminatorMap({"image" = "Image"})
 * @ORM\HasLifecycleCallbacks
 */
abstract class Uploads
{
    protected $file;

    private $tempFileName;

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

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

    /**
     * @var string
     *
     * @ORM\Column(name="fileName", type="string", length=36, unique=true)
     */
    private $fileName; // UUID

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


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

    /**
     * Set date.
     *
     * @param \DateTime $date
     *
     * @return uploads
     */
    public function setDate($date)
    {
        $this->date = $date;

        return $this;
    }

    /**
     * Get date.
     *
     * @return \DateTime
     */
    public function getDate()
    {
        return $this->date;
    }

    /**
     * Set fileName.
     *
     * @param string $fileName
     *
     * @return uploads
     */
    public function setFileName($fileName)
    {
        $this->fileName = $fileName;

        return $this;
    }

    /**
     * Get fileName.
     *
     * @return string
     */
    public function getFileName()
    {
        return $this->fileName;
    }

    /**
     * Set extension
     *
     * @param string $extension
     *
     * @return string
     */
    public function setExtension($extension)
    {
        $this->extension = $extension;

        return $this;
    }

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

    public function getFileNameExt()
    {
        return $this->getFileName().'.'.$this->getExtension();
    }

    public function setFile(UploadedFile $file)
    {
        $this->file = $file;
        if (null !== $this->getId()) {
            $this->tempFileName = $this->getFileNameExt();
            $this->fileName = null;
            $this->extension = null;
        }
    }

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

    /**
    * @ORM\PrePersist()
    * @ORM\PreUpdate()
    */
    public function preUpload()
    {
        if (null === $this->file) {
            return;
        }
        $this->extension = $this->file->guessExtension();
        $this->fileName = UUID::v4();
        $this->preUpdateFile();
    }

    protected function preUpdateFile(){} // To define if specific treatment

    /**
     * @ORM\PrePersist()
     */
    public function prePersistDate()
    {
        $this->date = new \DateTime();
        return $this;
    }

    /**
    * @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 = $this->file->move(
            $this->getUploadRootDir(),
            $this->getFileNameExt()
        );

        $this->postUpdateFile();
    }

    protected function postUpdateFile(){} // To define if specific treatment

    /**
    * @ORM\PreRemove()
    */
    public function preRemoveUpload()
    {
        // On sauvegarde temporairement le nom du fichier
        $this->tempFileName = $this->getFileNameExt();
        $this->preRemoveFile();
    }

    protected function preRemoveFile(){} // To define if specific treatment

    /**
    * @ORM\PostRemove()
    */
    public function removeUpload()
    {
        $oldFile = $this->getUploadRootDir().$this->tempFileName;
        if (file_exists($oldFile)) {
            unlink($oldFile);
        }
        $this->postRemoveFile();
    }

    protected function postRemoveFile(){} // To define if specific treatment

    public function getFileUri()
    {
        return $this->getUploadDir().$this->getFileNameExt();
    }

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

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

    public function __toString() {
        return $this->getFileNameExt();
    }
}

Entity \ Image.php具有自己的约束和文件管理的特定类型的上载

<?php

namespace Acme\CoreBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Image
 *
 * @ORM\Entity(repositoryClass="Acme\CoreBundle\Repository\ImageRepository")
 */
class Image extends Uploads
{
}

Entity \ WithImage.php需要Image的实体

<?php

namespace Acme\CoreBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * WithImage
 *
 * @ORM\Table(name="with_image")
 * @ORM\Entity(repositoryClass="Acme\CoreBundle\Repository\WithImageRepository")
 */
class WithImage
{

    /**
     * @ORM\OneToOne(targetEntity="Acme\CoreBundle\Entity\Image", cascade={"persist", "remove"})
     */
    protected $file;
}
forms symfony validation doctrine
1个回答
0
投票

我想到了一些想法来帮助你实现你想要的。

首先,你必须在一个表单中上传文件,并且约束应该在一个实体的属性中(除非你想要在每个表单中编写约束的痛苦,这不是很难以实现)。因此,对于将要拥有文件的每个实体,定义文件属性(不是ORM anotated)并在那里编写约束。还要添加相应的getter和setter。

/**                                                                         
 * @var UploadedFile                                                        
 * @Assert\NotBlank(groups={"New"})                                         
 * @Assert\File(mimeTypes={"text/html", "text/markdown", "text/plain"})     
 */                                                                         
private $file;

其次,您可能会问¿但是如何将它们保存到其他实体?这是我建议你使用Doctrine事件订阅者的时候。基本上,是一个使用doctrine.event_subscriber标记定义的服务,该类实现了Doctrine\Common\EventSubscriber接口。你可以订阅像preUpdatepostLoad这样的活动,以及有趣的你:prePersist

我对此的看法是你订阅了prePersist事件。该事件将传递给您实体(我们创建的文件非orm属性,其中包含保存文件信息的UploadedFile实例)。

然后,使用该文件的信息,创建一个新的上传实体,传递所需的所有信息,然后在真实文件orm映射属性中设置该属性,该属性保存与所需实体的文件关系。为此,如果我没记错的话,你必须启用持久级联。

这样做的好处:1。您可以在实体中定义约束。 2.您可以拥有所需的上传实体。

唯一的主要问题是您必须通过侦听器检索,存储和更新Uploads实体。但是我唯一能想到的就是帮助你。

© www.soinside.com 2019 - 2024. All rights reserved.