Как изменить данные с помощью событий API-платформы перед их записью

У меня есть пользователь и университетская сущность с отношением ManyToOne (в одном университете может быть много пользователей). Я добавил ограничение на уникальность названия университета, чтобы избежать дублирования.

Поэтому, когда я выполняю HTTP-запрос PUT по маршруту / users / $ id с полезной нагрузкой, содержащей существующее название университета, я получаю следующее:

Integrity constraint violation: 1062 Duplicate entry 'INSA' for key 'unique_university_name'

Я бы хотел, чтобы доктрина записала запись в базу данных, чтобы изменить ее, если она уже существует.

Для этого я попытался использовать систему событий API-платформы: https://api-platform.com/docs/core/events

С помощью событий kernel.request я мог получить доступ к данным, но не смог их изменить. Я не нашел способа изменить «содержание» запроса. Я пробовал также это: Есть ли способ изменить тело запроса в event_listener ядра Symfony, и я получил эту ошибку.

Serialization for the format html is not supported

Я хотел сделать это с помощью событий kernel.view, таких как PRE_VALIDATE, POST_VALIDATE или PRE_WRITE, но они не запускаются по какой-то причине.

Я использую правильный подход? Что мне делать, чтобы добавить университет к пользователю, если он уже существует на основании своего «названия»?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
1
0
3 904
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если я правильно понимаю, вы хотите изменить свой объект university, встроенный в ваш объект user.

Если вы следуете документации и делаете это так, то это не сработает, потому что основным объектом является экземпляр User.

$object = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$object instanceof University || Request::METHOD_POST !== $method) {
  return;
}

Один из способов сделать это:

$object = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$object instanceof User || Request::METHOD_POST !== $method) {
  return;
}

$university = $user->getUniversity();
// modify or replace your university here.

Другой подход заключается в использовании подписчик на событие доктрины, имейте в виду, что он выполняется после проверка сущности.

Ответ принят как подходящий

Чтобы решить вашу проблему, я вижу 3 возможности:


Вот как создать свой собственный денормализатор:

use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

final class UniversityDenormalizer implements DenormalizerInterface
{
    private $decoratedDenormalizer;
    private $repository;
    public function __construct(DenormalizerInterface $decorated, UniversityRepository $repository) {
        $this->repository = $repository;
        $this->decoratedNormalizer = $decorated;
    }

    public function denormalize($data, $class, $format = null, array $context = array())
    {
        if ($count = $this->repository->countUniversitiesStartingBy($data['name'])) {
            $data['name'] .= '_' . ($this->repository->countUniversities() + 1);
        }
        return $this->decoratedDenormalizer->denormalize($data, $class, $context);
    }

    public function supportsDenormalization($data, $type, $format = null)
    {
        return is_string($data) && University::class === $type;
    }
}

Также необходимо зарегистрировать его как услугу:

App\Serializer\UniversityDenormalizer:
    arguments:
        # Choose the denormalizer depending on your output.
        # For example, for JSON+LD it's "api_platform.jsonld.normalizer.item"
        - '@api_platform.json.normalizer.item'
        - '@App\Repository\UniversityRepository'
    tags:
        # Priority is important but any value more than 8 should be ok
        - { name: serializer.normalizer, priority: 17 }

Настраиваемая денормализация не работала. Она выдавала ошибку 500 без какого-либо сообщения, прослушиватель доктрины при предварительном сохранении по какой-то причине не запускался, и, к счастью, библиотека DomainComponent работала!

Sandoche 01.06.2018 15:08

Другие вопросы по теме