【发布时间】:2017-12-28 23:36:15
【问题描述】:
感谢您的关注,
简短
我想在一个实体中管理我所有的上传(图像、PDF、视频等),所以我使用实体继承来获取各种“类型”和 OneToOne 关系,以将父实体与正确的上传链接起来。我没有找到任何捆绑包来执行此操作并遇到问题:
- 约束使用
- 设置上传文件而不是上传实体
- 获取上传的文件而不是上传实体(版)
长
我宁愿在每个表中只使用一个表 Uploads 来处理每个上传,而不是在每个表中进行 1 个文件管理(这很冗长)。然后我只需要做 OneToOne 关系来获取我的文件,再加上使用继承,我可以根据 Image 或 PDF 应用各种处理。
我至少有 4 个实体需要图像,所以我认为 1to1 关系是一个不错的选择。
但我在做这样的事情时遇到了问题:
-
Constraints没有考虑到 -
$file的版本应设置为$file->file(它不会从Uploads/Image发送实体,而是用于创建此实体的文件 - 上传的文件未在实体版本上加载,每次编辑实体时都应重新上传
有人这样做吗?我不知道如何正确实现这一点。
查看我尝试的断言问题:
- 在
Image上定义断言(这不能按预期工作,因为表单的目标是$file的WithImage)- 使用注解
@Assert\Image() - 使用
loadValidatorMetadata - 使用注解
@Assert\Callback()
- 使用注解
- 在表单字段
'constraints' => array(new Assert\Image())上定义断言,这可行,但需要在我使用它的任何地方定义...
看着 setter 被误用,我找到了一种解决方法,但这很丑:
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 但这似乎不适用于我的情况)
代码
所以我将我的课程设计如下:
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