php - How to map one class variable to two form fields in Symfony
I wold like to use Symfony 2.8 to create a form for data class, e.g.Task
as used in the Symfony docs.
MyTask
class uses an integer fieldflags
to store a collection different bool values. For example the value ofis completed
is stored as the first bit andis urgent
as the second bit:
- Task is not completed and not urgent --> flags = 0
- Task is completed and not urgent --> flags = 1
- Task is not completed and urgent --> flags = 2
- Task is completed and urgent --> flags = 3
- ...
The problem: How can this single class field be mapped to two different form fields and back?
$builder
// map first bit to checkbox
->add('is_complete', CheckboxType::class, array(
...
)
)
// map second bit to selection box "normal"/"urgent"
->add('is_urgend', ChoiceType::class, array(
...
)
)
...
What is the correct solution to solve this? Can this be handled by a Data Transformers? As far as I know, a transformer can translate a field of one to type to another type, but not one field to two fields. Is that correct?
The only solution I found so far, is to create a wrapper classTaskWrapper
which does not use flags but offers different bool fields for the each flag value. This class could than be passed to the form instead of the originalTask
class. Once the form is submitted the returned wrapper object could than be manually translated back to aTask
object.
This would work, but it is not a clean solution. Is this the way to go or is there a better solution using Symfony tools?
Answer
Solution:
I would go for multiple boolean properties. It is easier at form-level and at persistence-level.
If you require to use that
$flags
property and you are using Doctrine, you can take use of the multiple boolean properties without mapping them. When submitting a form the fields are mapped directly to the entity properties except for those withmapped = false
: http://symfony.com/doc/current/reference/forms/types/form.html#mappedThen implement an eventlistener for events
prePersist
andpreUpdate
that set theflags
property before creating/updating the Task:For keeping consistency you can set the
$urgent
and$complete
property values throughsetFlags()
, since it will only be called either manually or when loading the entity.