У меня есть пользователь и университетская сущность с отношением 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, но они не запускаются по какой-то причине.
Я использую правильный подход? Что мне делать, чтобы добавить университет к пользователю, если он уже существует на основании своего «названия»?




Если я правильно понимаю, вы хотите изменить свой объект 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 работала!