Paolito75
Paolito75

Reputation: 568

Symfony form - Choicetype - Error "Array to string conversion"

I'm running Symfony 3.4 with FosUserBundle. I customized the registration form in order to get the Roles included:

$form->add('roles', ChoiceType::class, array(
    'choices' => array(
        'user' => 'ROLE_USER',
        'admin' => 'ROLE_ADMIN'
    ),
    'label' => 'Role :',
    'expanded' => true,
    'multiple' => true
));

Then roles are now selectable in the registration form through 2 new checkbox... but I'd like to display it with a <select> tag. When I set the expanded option to false I get a select, but if I set the multiple option to FALSE I get an error:

Array to string conversion

Any idea to fix my issue?

Below is the stack trace:

Symfony\Component\Debug\Exception\ContextErrorException:
Notice: Array to string conversion

  at vendor\symfony\symfony\src\Symfony\Component\Form\ChoiceList\ArrayChoiceList.php:73
  at Symfony\Component\Form\ChoiceList\ArrayChoiceList->Symfony\Component\Form\ChoiceList\{closure}(array('ROLE_USER'))
  at call_user_func(object(Closure), array('ROLE_USER'))
     (vendor\symfony\symfony\src\Symfony\Component\Form\ChoiceList\ArrayChoiceList.php:158)
  at Symfony\Component\Form\ChoiceList\ArrayChoiceList->getValuesForChoices(array(array('ROLE_USER')))
     (vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer.php:32)
  at Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer->transform(array('ROLE_USER'))
     (vendor\symfony\symfony\src\Symfony\Component\Form\Form.php:1104)
  at Symfony\Component\Form\Form->normToView(array('ROLE_USER'))
     (vendor\symfony\symfony\src\Symfony\Component\Form\Form.php:350)
  at Symfony\Component\Form\Form->setData(array('ROLE_USER'))
     (vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper.php:49)
  at Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper->mapDataToForms(object(User), object(RecursiveIteratorIterator))
     (vendor\symfony\symfony\src\Symfony\Component\Form\Form.php:383)
  at Symfony\Component\Form\Form->setData(object(User))
     (vendor\friendsofsymfony\user-bundle\Controller\RegistrationController.php:70)
  at FOS\UserBundle\Controller\RegistrationController->registerAction(object(Request))
  at call_user_func_array(array(object(RegistrationController), 'registerAction'), array(object(Request)))
     (var\cache\dev\classes.php:4659)
  at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
     (var\cache\dev\classes.php:4614)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor\symfony\symfony\src\Symfony\Component\HttpKernel\Kernel.php:200)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (web\app_dev.php:29)

Upvotes: 6

Views: 8627

Answers (3)

Kerrial Beckett Newham
Kerrial Beckett Newham

Reputation: 360

2020 - Symfony 5.0.8:

in your FormType file:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('roles', ChoiceType::class, [
            'required' => true,
            'multiple' => false,
            'expanded' => false,
            'choices'  => [
                'User' => 'ROLE_USER',
                'Admin' => 'ROLE_ADMIN',
            ],
        ]);

    $builder->get('roles')
        ->addModelTransformer(new CallbackTransformer(
            function ($rolesArray) {
                // transform the array to a string
                return count($rolesArray)? $rolesArray[0]: null;
            },
            function ($rolesString) {
                // transform the string back to an array
                return [$rolesString];
            }
        ));
}

Upvotes: 6

Abdelhafid El Kadiri
Abdelhafid El Kadiri

Reputation: 592

to solve your problem you need a data transformer, because the roles field is actually an array :

add the data transformer to your FormType class along with the roles field instead of adding it in the controller:

$builder->add('roles', ChoiceType::class, array(
    'choices' => array(
        'user' => 'ROLE_USER',
        'admin' => 'ROLE_ADMIN'
    ),
    'label' => 'Role :'
));

//roles field data transformer
$builder->get('roles')
    ->addModelTransformer(new CallbackTransformer(
        function ($rolesArray) {
             // transform the array to a string
             return count($rolesArray)? $rolesArray[0]: null;
        },
        function ($rolesString) {
             // transform the string back to an array
             return [$rolesString];
        }
));

Upvotes: 11

letibelim
letibelim

Reputation: 384

What is happening is normal : Your property roles is AN ARRAY of string. In your entity you got something like :

/**
 * @var array
 */
private $roles = [];

And logically, when you put the option multiple => 'true', Symfony form will treat it like an array and convert each element of your array in string (which they already are).

On the other hand, if you put multiple => false, it will consider the array as a single choice which it is not.

Simply put, you have an inconsistency between your model where your roles property is an array of string, and the form you are trying to create, which considers roles as a single value.

In your case, You have to put multiple => true.

Upvotes: 4

Related Questions