I have a simple Symfony API which uses FOSRestBundle. I have an Exercise
entity which contains a field sentences
. This field is of type json @ORM\Column(type="json")
and is stuffed with some nested json. The entity is persisted in a MySQL database.
I use Symfony forms to validate incoming data from a SPA. Here's the data the SPA sends on the endpoint /exercise
:
{
"name": "HEP9H",
"sentences": [
{
"name": "Sentence",
"tirettes": [
{
"chain": null
},
{
"chain": {
"name": "Chain 1"
}
}
]
}
]
}
Once persisted, the API then returns the entity as JSON. It should look exactly the same, except that it has an ID. The issue is that I get this piece of JSON in return:
{
"id": 21,
"name": "HEP9H",
"sentences": [
{
"name": "Sentence",
"tirettes": [
{
"chain": {
"name": null
}
},
{
"chain": {
"name": "Chaîne 1"
}
}
]
}
]
}
As you can see, the problem is that my property "chain": null
becomes "chain": {"name": null}
. I guess this is due to a bad form type configuration. The data structure changes right after I validate my form and before I persist the entity for the first time.
Here's TiretteType:
class TiretteType extends AbstractType {
public function buildForm ( FormBuilderInterface $builder, array $options ) {
$builder
->add ( 'chain', ChainType::class, [
"required" => false
] );
}
}
And here's ChainType:
class ChainType extends AbstractType {
public function buildForm ( FormBuilderInterface $builder, array $options ) {
$builder->add ( 'name', TextType::class );
}
}
I have no underlying data class and no underlying entity (except the root entity Exercise
).
What I've tried so far:
"required" => false
to the 'chain' field, it doesn't change anything"empty_data" => NULL
to the 'chain' field, this also doesn't work and overrides any data to NULLAm I completely missing something?
Thanks!
I found the answer to my issue. Since my field chain
had no underlying data class, the form would simply give me an array with default values if it had a null
value as input.
The solution is to use a data transformer (https://symfony.com/doc/current/form/data_transformers.html). I had to check for such an empty structure and if found, return back null
instead of the given value.
$builder->get ( 'chain' )->addModelTransformer ( new CallbackTransformer(
function ( $originalInput ) {
return $originalInput;
},
function ( $submittedValue ) {
return $submittedValue["name"] === null ? $submittedValue : null;
}
) );
I don't think checking for null properties is the cleanest way to do this but my case is very simple so I won't spend more time on this one.
Hope this helps someone.