Symfony + FOSRestBundle — Как разрешить значение NULL для поля, настроенного с помощью пользовательского типа формы?

У меня есть простой Symfony API, который использует FOSRestBundle. У меня есть сущность Exercise, которая содержит поле sentences. Это поле имеет тип json @ORM\Column(type = "json") и заполнено каким-то вложенным json. Сущность сохраняется в базе данных MySQL.

Я использую формы Symfony для проверки входящих данных из SPA. Вот данные, которые SPA отправляет на конечную точку /exercise:

{
    "name": "HEP9H",
    "sentences": [
        {
            "name": "Sentence",
            "tirettes": [
                {
                    "chain": null
                },
                {
                    "chain": {
                        "name": "Chain 1"
                    }
                }
            ]
        }
    ]
}

После сохранения API возвращает объект в формате JSON. Он должен выглядеть точно так же, за исключением того, что у него есть идентификатор. Проблема в том, что я получаю этот кусок JSON взамен:

{
  "id": 21,
  "name": "HEP9H",
  "sentences": [
    {
      "name":  "Sentence",
      "tirettes": [
        {
          "chain": {
            "name": null
          }
        },
        {
          "chain": {
            "name": "Chaîne 1"
          }
        }
      ]
    }
  ]
}

Как видите, проблема в том, что моя собственность "chain": null становится "chain": {"name": null}. Я предполагаю, что это связано с плохой конфигурацией типа формы. Структура данных меняется сразу после проверки формы и до того, как я впервые сохраняю сущность.

Вот ТиретТип:

class TiretteType extends AbstractType {

    public function buildForm ( FormBuilderInterface $builder, array $options ) {
        $builder
            ->add ( 'chain', ChainType::class, [
                "required" => false
            ] );
    }
}

А вот и ChainType:

class ChainType extends AbstractType {

    public function buildForm ( FormBuilderInterface $builder, array $options ) {
        $builder->add ( 'name', TextType::class );
    }
}

У меня нет базового класса данных и базовой сущности (кроме корневой сущности Exercise).

Что я пробовал до сих пор:

  • добавление "required" => false в поле «цепочка» ничего не меняет
  • установка "empty_data" => NULL в поле «цепочка», это также не работает и переопределяет любые данные в NULL

Я что-то совсем упустил?

Спасибо!

Стоит ли изучать 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 нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
0
0
238
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Я нашел ответ на свой вопрос. Поскольку у моего поля chain не было базового класса данных, форма просто дала бы мне массив со значениями по умолчанию, если бы в качестве входных данных было значение null.

Решение состоит в использовании преобразователя данных (https://symfony.com/doc/current/form/data_transformers.html). Приходилось проверять такую ​​пустую структуру и, если находить, возвращать обратно null вместо заданного значения.

$builder->get ( 'chain' )->addModelTransformer ( new CallbackTransformer(
    function ( $originalInput ) {
        return $originalInput;
    },
    function ( $submittedValue ) {
        return $submittedValue["name"] === null ? $submittedValue : null;
    }
) );

Я не думаю, что проверка нулевых свойств — самый чистый способ сделать это, но мой случай очень прост, поэтому я не буду тратить на него больше времени.

Надеюсь, это поможет кому-то.

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