По умолчанию, путь до изображения хранится в виде названия файла. Чтобы превратить его в полный url - нужно вызывать хелпер. Но у нас ведь есть нормалайзеры! `class UploadableNormalizer implements NormalizerInterface { private array $classMetadataCache = [];
public function __construct( #[Autowire(service: 'serializer.normalizer.object')] private NormalizerInterface $normalizer, private UploaderHelper $uploaderHelper, private EntityManagerInterface $em, ) {}
public function normalize($object, ?string $format = null, array $context = []): array { // Сначала нормализуем как обычно, не забывая передать контекст // Там могут быть группы нормализации $data = $this->normalizer->normalize($object, $format, $context);
foreach ($this->extractUploadableFields($object) as $property => $propertyName) { if (empty($data[$propertyName])) { // Поле было удалено в результате нормализации continue; }
// Заменяем some.jpg на /uploads/fo/l/d/er/some.jpg $data[$propertyName] = $this->uploaderHelper->asset($object, $property); }
return $data; }
public function supportsNormalization($data, ?string $format = null, array $context = []): bool { if (!$this->em->contains($data)) { // Если сейчас сериализуется не доктриновский объект - не трогаем return false; }
$reflector = $this->em->getClassMetadata($data::class)->getReflectionClass();
// Сущность должна быть помечена, как бандловая $attrs = $reflector->getAttributes(Uploadable::class);
return !empty($attrs); }
public function getSupportedTypes(?string $format): array { // Данный нормализатор работает только с объектами // true ознаечает кешировать результат supports* return ['object' => true]; }
private function extractUploadableFields(object $object): array { // Забираем у доктрины рефлектор $reflector = $this->em->getClassMetadata($object::class)->getReflectionClass(); $className = $reflector->getName();
if (!isset($this->classMetadataCache[$className])) { // Пользуемся кешированием, чтобы для одного класса не парсить каждый раз $fields = [];
foreach ($reflector->getProperties() as $property) { // Перебираем свойства и забираем те, которыми управляет бандл $attrs = $property->getAttributes(UploadableField::class);
foreach ($attrs as $attr) { $uploadableField = $attr->newInstance(); $fields[$property->getName()] = $uploadableField->getFileNameProperty(); } }
$this->classMetadataCache[$className] = $fields; }
return $this->classMetadataCache[$className]; } } Из минусов - если кто-то напишет еще один нормалайзер на нашу сущность - они друг друга перетирать начнут. Но, я стараюсь прибегать к магии универсальных нормалайзеров как можно реже. Большую часть проблем можно разрулить на уровне групп нормализации и виртуальных геттерах.`