-->

Symfony2 Forms BooleanToStringTransformer Issue

2019-06-24 15:06发布

问题:

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?

回答1:

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;
    }
}


回答2:

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.



回答3:

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);
    }
})