I have a boolean field that I've put in a form as a choice field (yes or no).
I would get 0 or 1 without data transformer.
I added a view BooleanToStringTransformer (which seemed reasonable) :
$builder
->add(
$builder->create('myBooleanField', 'choice', array(
'choices' => array(true => 'Yes', false => 'No'),
))
->addViewTransformer(new BooleanToStringTransformer('1'))
)
And when I try to display the form, I get the error "Expected a Boolean.".
My field is set to false before creating the form though.
I tried to set it as a model transformer: the form is dispayed, but when I submit it my field is declared invalid.
What am I doing wrong?
Edit: I nearly got it now.
- I used a model transformer instead of a view transformer (the choice field works with strings or integers, not booleans)
- I changed my choice list from
array(true => 'Yes', false => 'No')
to array('yes' => 'Yes', 'no' => 'No')
So the code now looks like ->addModelTransformer(new BooleanToStringTransformer('yes'))
Data transformation works, except that my field is always set to true, whatever value I choose.
What's wrong?
The answer is: I shouldn't have thought the default Symfony BooleanToStringDataTransformer was doing the job. It returns null for a false value instead of a string.
So I created my own datatransformer:
<?php
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
class BooleanToStringTransformer implements DataTransformerInterface
{
private $trueValue;
private $falseValue;
public function __construct($trueValue, $falseValue)
{
$this->trueValue = $trueValue;
$this->falseValue = $falseValue;
}
public function transform($value)
{
if (null === $value) {
return null;
}
if (!is_bool($value)) {
throw new TransformationFailedException('Expected a Boolean.');
}
return true === $value ? $this->trueValue : $this->falseValue;
}
public function reverseTransform($value)
{
if (null === $value) {
return null;
}
if (!is_string($value)) {
throw new TransformationFailedException('Expected a string.');
}
return $this->trueValue === $value;
}
}
You seem to have used a View transformer instead of a Model transformer. You'll need to reverse-transform 0/1 to boolean in the Model transformer if the underlying model expects boolean values.
.. or you might have missed to implement the reverse-transform method in your view transformer.
Read more about the difference between View and Model transformers here.
Another workaround can be:
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$data = $event->getData();
if (isset($data['myBooleanField'])) {
$data['myBooleanField'] = (bool) $data['myBooleanField'];
$event->setData($data);
}
})