xaduken/image-symfony-support

组件,用于使symfony中的图像管理变得非常简单

v1.0.3 2022-08-17 02:19 UTC

This package is auto-updated.

Last update: 2024-09-28 14:12:19 UTC


README

描述

用于将图像信息持久化到数据库并存储到文件系统中的组件。

安装

composer require xaduken/image-symfony-support

用法

假设你有一个实体User。这个实体需要有一个头像。然后你可以创建一个Image实体,并使其实现Imageable接口。这样你就可以保证数据库中的Image表将具有必要的列。

Image实体可能如下所示

<?php

namespace App\Entity;

use App\Repository\ImageRepository;
use DateTimeImmutable;
use Doctrine\ORM\Mapping as ORM;
use Xaduken\ImageSupport\EntityInterface\Imageable;

#[ORM\Entity(repositoryClass: ImageRepository::class)]
#[ORM\HasLifecycleCallbacks]
class Image implements Imageable
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $related_entity = null;

    #[ORM\Column(length: 400, nullable: true)]
    private ?string $path = null;

    #[ORM\Column(length: 255)]
    private ?string $fileName = null;

    #[ORM\Column(length: 255)]
    private ?string $mimeType = null;

    #[ORM\Column]
    private ?DateTimeImmutable $createdAt = null;

    #[ORM\Column]
    private ?DateTimeImmutable $updatedAt = null;

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

    public function getRelatedEntity(): ?string
    {
        return $this->related_entity;
    }

    public function setRelatedEntity(string $related_entity): self
    {
        $this->related_entity = $related_entity;

        return $this;
    }

    public function getPath(): ?string
    {
        return $this->path;
    }

    public function setPath(?string $path): self
    {
        $this->path = $path;

        return $this;
    }

    public function getFileName(): ?string
    {
        return $this->fileName;
    }

    public function setFileName(string $fileName): self
    {
        $this->fileName = $fileName;

        return $this;
    }

    public function getMimeType(): ?string
    {
        return $this->mimeType;
    }

    public function setMimeType(string $mimeType): self
    {
        $this->mimeType = $mimeType;

        return $this;
    }

    public function getCreatedAt(): ?DateTimeImmutable
    {
        return $this->createdAt;
    }

    public function setCreatedAt(DateTimeImmutable $createdAt): self
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    public function getUpdatedAt(): ?DateTimeImmutable
    {
        return $this->updatedAt;
    }

    public function setUpdatedAt(DateTimeImmutable $updatedAt): self
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    #[ORM\PreUpdate]
    public function onUpdate(): void
    {
        $this->updatedAt = new DateTimeImmutable();
    }

    #[ORM\PrePersist]
    public function onCreate(): void
    {
        $this->createdAt = new DateTimeImmutable();
        $this->updatedAt = new DateTimeImmutable();
    }
}

如你所见,Image实体实现了Imageable接口。这是必需的。

之后,你需要创建UserImageManager并扩展它以使用AbstractImageManager。

UserImageManager

<?php

namespace App\Image;

use App\Entity\Image;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Xaduken\ImageSupport\Factory\ImageManagerFactoryInterface;
use Xaduken\ImageSupport\Factory\SimpleImageManagerFactory;
use Xaduken\ImageSupport\Service\AbstractImageManager;

class UserImageManager extends AbstractImageManager
{
    private EntityManagerInterface $entityManager;

    private string $targetDir;

    public function __construct(EntityManagerInterface $entityManager, string $targetDir)
    {
        $this->entityManager = $entityManager;
        $this->targetDir = $targetDir;
    }

    protected function getTargetDirectory(): string
    {
        return $this->targetDir;
    }

    protected function getRelatedClass(): string
    {
        return User::class;
    }

    protected function getImageManagerFactory(): ImageManagerFactoryInterface
    {
        return new SimpleImageManagerFactory($this->getEntityManager());
    }

    protected function getEntityManager(): EntityManagerInterface
    {
        return $this->entityManager;
    }

    protected function getImageEntityClass(): string
    {
        return Image::class;
    }
}

让我们更详细地看看方法。

getTargetDirectory()

用于定义用户图像应存储的路径。在这种情况下,我们将其推送到构造函数并通过属性传递。你也可以使用其他任何方式来做这件事。

getRelatedClass()

在此处推送应存储在table references to defined entity in getImageEntityClass方法中related_class列的完整类名。

getImageManagerFactory()

在此处推送ImageManagerFactoryInterface的类实例。请查看此文件末尾的完整工厂列表。

getEntityManager()

在此处推送doctrine entityManager。在这个例子中,我们从构造函数中获取它。在用法示例中,我们从依赖注入中获取它。

getImageEntityClass()

在此处推送实现Imageable接口的实体实现的完整类名。在这种情况下是Image实体。

测试

在创建UserImageManager后,我们就可以使用一个简单的类将我们的文件存储到数据库和文件系统中了!

查看示例

<?php

namespace App\Controller\Api;

use App\Image\UserImageManager;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class TestController extends AbstractController
{
    #[Route(path: '/api/test-image', name: 'test-image')]
    public function testImage(Request $request, UserImageManager $userImageManager): Response
    {
        $image = $request->files->get('image');

        $result = $userImageManager->save($image);

        dd(result);
    }
}

我们通过依赖注入获取UserImageManager并使用一个方法将图像保存到数据库、文件系统并管理其关系!

但也许你会问UserImageManager类如何获得$targetDirectory属性?这很简单。只需使用symfony手动注入。

/config/services.yaml

parameters:
    ...
    user_image_directory: '%kernel.project_dir%/public/uploads/user'
services:
    ...
    App\Image\UserImageManager:
        arguments:
            $targetDir: '%user_image_directory%'

就是这样!现在,如果你需要保存与User实体相关的图像。只需通过依赖注入获取UserEntityManager并保存你的图像。

工厂

这很酷,但如果在保存到文件系统之前需要调整图像大小呢?还有其他一些事情呢?为了回答这些问题,我使用了抽象工厂模式。

如果你需要定义定制的实现方式,请创建自己的工厂,实现ImageManagerFactoryInterface,并将你的实现推送到UserImageManger.getImageManagerFactory()方法。

ImageManagerFactoryInterface有非常简单的签名,让我们看看

ImageManagerFactoryInterface

<?php

namespace Xaduken\ImageSupport\Factory;

use Xaduken\ImageSupport\Database\DatabaseImageUploaderInterface;
use Xaduken\ImageSupport\Filesystem\FilesystemUploaderInterface;

interface ImageManagerFactoryInterface
{
    public function getDatabaseUploader(): DatabaseImageUploaderInterface;

    public function getFilesystemUploader(): FilesystemUploaderInterface;
}

让我们更详细地看看方法

getDatabaseUploader()

应该返回一个实现DatabaseImageUploaderInterface的类实例。你应该创建这个实现。这个类应该定义如何将Imageable实体持久化到数据库。对于简单的持久化,可以使用DatabaseImageUploader类实例。

我们将在后面讨论如何创建DatabaseUploaderInterface的实现。

getFilesystemUploader()

应该返回一个实现FilesystemUploaderInterface的类实例。你也应该自行实现或使用StandardFilesystemUploader(如果你需要简单的保存)。

就像我们讨论过的DatabaseImageUploaderInterface一样,我们将在后面讨论如何实现。

DatabaseImageUploaderInterface

它的签名非常简单

<?php

namespace Xaduken\ImageSupport\Database;

use Xaduken\ImageSupport\DTO\ImageInfo;
use Xaduken\ImageSupport\EntityInterface\Imageable;

interface DatabaseImageUploaderInterface
{
    public function upload(ImageInfo $imageInfo, string $relatedEntity, string $imageClass): Imageable;
}

upload方法应将Image保存到数据库。

  • $imageInfo - 是一个简单的DTO类,在将图像保存到文件系统后会返回。
  • $relatedEntity - 使用它将$relatedEntity设置为Imageable实体。
  • $imageClass - 通过此属性创建 Imageable 对象。

FilesystemUploaderInterface

它们的签名与 DatabaseImageUploaderInterface 非常相似。

<?php

namespace Xaduken\ImageSupport\Filesystem;

use Symfony\Component\HttpFoundation\File\UploadedFile;
use Xaduken\ImageSupport\DTO\ImageInfo;

interface FilesystemUploaderInterface
{
    public function upload(UploadedFile $uploadedFile, string $targetDirectory): ImageInfo;
}

upload 方法应将图像保存到文件系统。

  • $uploadedFile - 来自 symfony 请求的文件
  • $targetDirectory - 文件将保存的目录

方法应返回 FileInfo DTO 对象,该对象将用于存储到数据库中。

也许你会在列表中找到工厂实现的“针”

  • SimpleImageManagerFactory - 仅保存图像到数据库和文件系统。

目前不是很多;(