symfony自定义序列化类

Mario Sanchez

20 people read
Thumbnail

自定义序列化

在symfony开发中,特别是使用api-platform进行开发时,整个entity可以很方便的被序列化与反序列化

设想有这样一个场景:

你的entity有一个字段存放的是上传文件的路径,但是这个文件是放在oss上的,并且使用了私有读写,所以每一次访问时都需要根据文件路径去生成鉴权访问url

一般的做法是针对整个entity写一个自定义的序列化类,假如你有几十上百个entity,每一个都有同样的需求,那么重复写序列化类就太浪费了。所以今天我们来写一个注解方式的序列化。

对于我个人来说,我喜欢把这个字段定义为json格式,因为文件可能是一个可能是多个,而每一个json里我会存放路径、文件原名、上传后的文件名、大小、格式等数据

代码如下:

# src/Entity/SomeEntity.php

    #[ORM\Column(length: 255)]
    #[Groups(['expert.read'])]
    private array $media = [];

现在我们用命令创建一个自定义序列化类:

php bin/console make:serializer:normalizer

生成MediaNormalizer.php,然后在Entity的属性上加上注解:

    #[ORM\Column(length: 255)]
    #[Groups(['expert.read'])]
    #[Context([MediaNormalizer::SERIALIZER_MEDIA=>true])]
    private array $media = [];

接下来我们看看MediaNormalizer.php:

<?php

namespace App\Serializer\Normalizer;

use App\Service\FileUploadService;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class MediaNormalizer implements NormalizerInterface, NormalizerAwareInterface
{
    use NormalizerAwareTrait;

    const SERIALIZER_MEDIA = 'media_array';

    public function __construct(
        private FileUploadService $fileUploadService
    )
    {
    }

    public function normalize($object, ?string $format = null, array $context = []): array
    {
        foreach ($object as $key => $item) {
            if (is_array($item) && isset($item['path'])) {
                $object[$key]['url'] = $this->fileUploadService->readFile($item['path']);
            } else {
                if ($key === 'path') {
                    $object['url'] = $this->fileUploadService->readFile($item);
                }
            }
        }
        return $object;
    }

    public function supportsNormalization($data, ?string $format = null, array $context = []): bool
    {
        return is_iterable($data) && key_exists(self::SERIALIZER_MEDIA, $context);
    }

    public function getSupportedTypes(?string $format): array
    {
        return ['object' => null, '*' => true];
    }
}

在getSupportedTypes方法中我们返回了支持缓存的属性, 然后在supportsNormalization中我们判断data是不是array,并且在content数组中media_array是否存在。在这两个条件都满足情况下 说明就是我们需要进行序列化的字段。 然后在normalize中进行读取oss文件的逻辑。整个代码就完成了,使用也非常的方便

About Me

我是一位精通 Symfony 框架和 API Platform 的开发者,擅长构建高效、可扩展的 Web 应用程序和 API。 此外,我还具备 PrestaShop 模块开发经验,能够为您的电商平台定制功能,满足特定业务需求。