今天我试图通过在监听器中创建postLoad函数来“改进”我的文件上传,这样我就可以从控制器中移动所有关于文件的代码。
这是旧的添加(文件不是强制性的):
$file = $accommodation->getMainImage()->getFile();
if ($file != null) {
$fileName = $this->get('app.image_uploader')->upload($file);
$accommodation->getMainImage()->setFile($fileName);
} else {
$accommodation->setMainImage(null);
}
这是旧编辑:
表单提交前:
if ($accommodation->getMainImage() != null) {
$oldFile = $accommodation->getMainImage()->getFile();
}
提交后:
$file = $accommodation->getMainImage()->getFile();
if ($file != null) {
$fileName = $this->get('app.image_uploader')->upload($file);
$accommodation->getMainImage()->setFile($fileName);
} else {
if (isset($oldFile)) {
$accommodation->getMainImage()->setFile($oldFile);
} else {
$accommodation->setMainImage(null);
}
}
此代码工作正常,但我想改进它
只需提交住宿并坚持住宿,就像这样:
if ($form->isSubmitted() && $form->isValid()) {
/** @var AccommodationBase $accommodation */
$accommodation = $form->getData();
$entityManager->persist($accommodation);
住宿包含一对一的图像
/**
* @ORM\OneToOne(targetEntity="Image", inversedBy="accommodationImageMain", cascade={"persist"})
* @ORM\JoinColumn(name="main_image_id", referencedColumnName="id", unique=false, nullable=true)
*/
private $mainImage;
这是图片:
class Image
{
/**
* @ORM\Column(type="string")
* @Assert\File(
* maxSize = "5M",
* mimeTypes = {"image/jpeg", "image/gif", "image/png", "image/tiff"},
* maxSizeMessage = "The maximum allowed file size is 5MB.",
* mimeTypesMessage = "Only image is allowed."
* )
*/
protected $file;
/**
* @ORM\OneToOne(targetEntity="AccommodationBase", mappedBy="mainImage")
*/
private $accommodationImageMain;
我使用symfony docs
逐步将方法postLoad添加到监听器class ImageUploadListener
{
private $uploader;
public function __construct(FileUploader $uploader)
{
$this->uploader = $uploader;
}
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
$this->uploadFile($entity);
}
public function preUpdate(PreUpdateEventArgs $args)
{
$entity = $args->getEntity();
$this->uploadFile($entity);
}
private function uploadFile($entity)
{
dump($entity);
if (!$entity instanceof Image) {
return;
}
$file = $entity->getFile();
// only upload new files
if (!$file instanceof UploadedFile) {
return;
}
$fileName = $this->uploader->upload($file);
$entity->setFile($fileName);
}
//this is new
public function postLoad(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if (!$entity instanceof Image) {
return;
}
if ($fileName = $entity->getFile()) {
$entity->setFile(new File($this->uploader->getTargetDir().'/'.$fileName));
}
}
}
这是我现有的服务
class FileUploader
{
private $targetDir;
public function __construct($targetDir)
{
$this->targetDir = $targetDir;
}
public function upload(UploadedFile $file)
{
$fileName = md5(mt_rand()).'.'.$file->guessExtension();
$file->move($this->targetDir, $fileName);
return $fileName;
}
public function getTargetDir()
{
return $this->targetDir;
}
}
之后我可以成功上传图片或在该实体上编辑图片,但如果我想在没有图片上传的情况下添加/编辑实体,我收到此错误:
执行'INSERT INTO image(文件, 创建,更新)VALUES(?,?,?)'与params [null,“2017-10-06 09:12:16“,”2017-10-06 09:12:16“]:
SQLSTATE [23000]:完整性约束违规:19 NOT NULL 约束失败:image.file 我知道我可以在控制器中检查它并保存旧图片,在坚持之前我可以添加它或像之前一样设置null。在监听器/服务中有什么办法吗?
我知道我可以在控制器中执行此操作:
如果添加:
if (empty($activity->getActivityLogo()->getFile())) {
$activity->setActivityLogo(null);
}
如果是编辑:
提交前:
if (!empty($activity->getActivityLogo())) {
$oldFile = $activity->getActivityLogo()->getFile();
}
提交后:
if (empty($activity->getActivityLogo()->getFile())) {
if (empty($oldFile)) {
$activity->setActivityLogo(null);
} else {
$activity->getActivityLogo()->setFile($oldFile);
}
}
但这与我之前的解决方案相同。还有可能使用一些“虚拟值”来保存Image实体,这对于性能而言并不是很好的控制