Let's start with a background.
I need user profile that will have basic info like name, email, phone etc. And for that I have an entity User.
I also need to store answers from a questionnaire. I was thinking to store them in database as a json in a text field. Those questions can change in the future, there are currently ~30 questions so I don't want to store it as an entity. So currently in my User entity I have this:
/**
* @var array
*
* @ORM\Column(name="questionnaire", type="json_array", nullable=true)
*/
private $questionnaire;
I understand that Symfony will take care of json_encode/json_decode thing. So this is great.
But now, I have a bit of problem with creating a form with the symfony builder.
First I thought I could try something like this:
$builder->add('questionnaire[source]');
Which doesn't work. For symfony masters it's obvious I know ;o)
So currently my choices I see are: CollectionType or Data Transformers.
From what I see, CollectionType will not work, as it's only work with numeric arrays where we have field with some JS "Add another row" or something. http://symfony.com/doc/current/reference/forms/types/collection.html#adding-and-removing-items But if I'm wrong about this and I should go with CollectionType and there is some magic way please tell me. I can't find much about this.
So I was thinking Data Transformers or simply creating an array on submit without this Transformer thing. Create all fields that are in Questionnaire with the "mapped=>false" and then set those submitted values as an associative array to $questionnaire. This "feels" ok, but I'm not sure how to later handle this in "Edit" form (from docs I think with this http://symfony.com/doc/current/reference/forms/types/form.html#data).
Questionnaire itself will have many ChoiceType fields, a CollectionType with "Add more row" and so on and it will have lots of questions. So it will be a bit complex. I would like to avoid creating entity for that with each question as a property (not sure if it's a right choice, but considering everything I believe it's the best one).
This is my first date with symfony so any help/tips appreciate.
in_array() function is utilized to determine if specific value exists in an array. It works fine for one dimensional numeric and associative arrays.
$_POST is a predefined variable which is an associative array of key-value pairs passed to a URL by HTTP POST method that uses URLEncoded or multipart/form-data content-type in request.
The most frequently used general purpose implementation of an associative array is with a hash table: an array combined with a hash function that separates each key into a separate "bucket" of the array.
After few days I found the answer for my own question. Bounty didn't helped to get it faster, but hey, there is a solution! ;o)
So turns out it's really simple. I've actually didn't found a lot on this particular problem, so in case you need something similar, here it is.
In the entity class with this json_array, define all needed keys like so:
/**
* @var array
*
* @ORM\Column(name="questionnaire", type="json_array", nullable=true)
*/
private $questionnaire = [
'favPet'=>'',
'favFood'=>'',
'favColor'=>''
];
Next, in the form builder use the "property_path"! It's that simple... https://symfony.com/doc/current/reference/forms/types/form.html#property-path like this:
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('email', EmailType::class)
->add('phone')
->add('address')
->add('favPet',TextType::class,[
'label'=>'Fav pet',
'property_path'=>'questionnaire[favPet]'
])
->add('favFood',TextType::class,[
'label'=>'Fav food',
'property_path'=>'questionnaire[favFood]'
])
->add('favColor',TextType::class,[
'label'=>'Fav color',
'property_path'=>'questionnaire[favColor]'
])
;
}
And symfony will handle the rest. Because we used json_array as a type, symfony will handle json_encode/json_decode thing. In order for symfony to map/populate values in edit mode the property must have it's key defined. Otherwise you will get error:
PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "NULL" while trying to traverse path
And then in the twig template you can do this:
{{ user.questionnaire.favPet }}
And that's it! :o))
As for the JSON or Entity. I know I wrote no entity, but I didn't made up my mind. After some IRC conversations, reading and this https://stackoverflow.com/a/4013207/531099 I will probably go with EAV. So if you are deciding between JSON vs Entity, add EAV to the race.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With