Symfony使用侦听器

时间:2017-10-06 07:29:20

标签: php sql forms symfony file-upload

今天我试图通过在监听器中创建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实体,这对于性能而言并不是很好的控制

0 个答案:

没有答案