24

I've read the other subjects but it doesn't solve my problem so:

I've got this

->add('role', 'choice', array(
                'label' => 'I am:',
                'mapped' => true,
                'expanded' => true,
                'multiple' => false,
                'choices' => array(
                    'ROLE_NORMAL' => 'Standard',
                    'ROLE_VIP' => 'VIP',
                ) 
            ))

And whatever I do, I get this error:

Notice: Array to string conversion in C:\xampp\htdocs\xxx\vendor\symfony\symfony  \src\Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList.php line 458 

In my form type the setRole method is not even called (when I rename it to some garbage the error still occurs). Why is this happening?

// EDIT

Full stack trace:

in C:\xampp\htdocs\xxx\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList.php at line 458  -

     */
    protected function fixIndex($index)
    {
        if (is_bool($index) || (string) (int) $index === (string) $index) {
            return (int) $index;
        }

    at ErrorHandler ->handle ('8', 'Array to string conversion', 'C:\xampp\htdocs     \xxx\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList.php', '458', array('index' => array()))
in C:\xampp\htdocs\xxx\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList.php at line 458  +
at ChoiceList ->fixIndex (array())
in C:\xampp\htdocs\xxx\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList.php at line 476  +
at ChoiceList ->fixIndices (array(array()))
in C:\xampp\htdocs\xxx\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList.php at line 152  +
at SimpleChoiceList ->fixChoices (array(array()))
in C:\xampp\htdocs\xxx\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList.php at line 204  +
at ChoiceList ->getIndicesForChoices (array(array()))
in C:\xampp\htdocs\xxx\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToBooleanArrayTransformer.php at line 63  +
at ChoiceToBooleanArrayTransformer ->transform (array())
in C:\xampp\htdocs\xxx\vendor\symfony\symfony\src\Symfony\Component\Form\Form.php at line 1019  +
at Form ->normToView (array())
in C:\xampp\htdocs\xxx\vendor\symfony\symfony\src\Symfony\Component\Form\Form.php at line 332  +
at Form ->setData (array())
in C:\xampp\htdocs\xxx\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper.php at line 59  +
at PropertyPathMapper ->mapDataToForms (object(User), object(RecursiveIteratorIterator))
in C:\xampp\htdocs\xxx\vendor\symfony\symfony\src\Symfony\Component\Form\Form.php at line 375  +
at Form ->setData (object(User))
in C:\xampp\htdocs\xxx\vendor\friendsofsymfony\user-bundle\FOS\UserBundle\Controller\RegistrationController.php at line 49  +
at RegistrationController ->registerAction (object(Request))
at call_user_func_array (array(object(RegistrationController), 'registerAction'), array(object(Request)))
in C:\xampp\htdocs\xxx\app\bootstrap.php.cache at line 2770  +
at HttpKernel ->handleRaw (object(Request), '1')
in C:\xampp\htdocs\xxx\app\bootstrap.php.cache at line 2744  +
at HttpKernel ->handle (object(Request), '1', true)
in C:\xampp\htdocs\xxx\app\bootstrap.php.cache at line 2874  +
at ContainerAwareHttpKernel ->handle (object(Request), '1', true)
in C:\xampp\htdocs\xxx\app\bootstrap.php.cache at line 2175  +
at Kernel ->handle (object(Request))
in C:\xampp\htdocs\xxx\web\app_dev.php at line 29  +
user2394156
  • 1,792
  • 4
  • 16
  • 33

4 Answers4

40

Symfony's trying to convert your $role(array property) to not multiple choice field(string).

There's several ways to deal with this problem:

  1. Set multiple to true in your choice form widget.
  2. Change mapping from array to string for $role property in your entity.
  3. If you insist to have above options unchanged, you can create DataTransformer. That's not the best solution because you will lose data if your array have more than 1 element.

Example:

<?php
namespace Acme\DemoBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

class StringToArrayTransformer implements DataTransformerInterface
{
    /**
     * Transforms an array to a string. 
     * POSSIBLE LOSS OF DATA
     *
     * @return string
     */
    public function transform($array)
    {
        return $array[0];
    }

    /**
     * Transforms a string to an array.
     *
     * @param  string $string
     *
     * @return array
     */
    public function reverseTransform($string)
    {
        return array($string);
    }
}

And then in your form class:

use Acme\DemoBundle\Form\DataTransformer\StringToArrayTransformer;
/* ... */
$transformer = new StringToArrayTransformer();
$builder->add($builder->create('role', 'choice', array(
                'label' => 'I am:',
                'mapped' => true,
                'expanded' => true,
                'multiple' => false,
                'choices' => array(
                    'ROLE_NORMAL' => 'Standard',
                    'ROLE_VIP' => 'VIP',
                )
              ))->addModelTransformer($transformer));

You can read more about DataTransformers here: http://symfony.com/doc/current/cookbook/form/data_transformers.html

gregory90
  • 569
  • 5
  • 5
  • 1
    I will when I get enough reputation, for sure – user2394156 Jun 28 '13 at 08:14
  • 1
    It might be worth noting that this answer works specifically on an array. If the form is referencing an object (eg. a User object as was my case), the transformer needs to reference from the User object. For example, in the transformer I used $user->getRoles()[0] in the "transform" function. – Ryan B Apr 08 '15 at 15:07
  • Your solution is true. However, it does not make sense. If your solution is based on losing data, it is not acceptable. @user2394156 You need only little bit change on your ORM file. Make sure that your field is array or json_array. So on, Symfony2 will insert your data as serialized or json data to database column. – Ali Emre Çakmakoğlu Jan 24 '16 at 18:38
2

Make sure that you use proper data type in ORM file. In this case, your role field cannot be string. It must be a many-to-many relation, array or json_array.

If you choose one of them, symfony will insert the data without effort or any type of transformer.

E.g.:

// Resources/config/User.orm.yml
fields:
  role:
      type: array
      nullable: false

So, it will live in your database as like:

a:2:{i:0;s:4:"user";i:1;s:5:"admin";}
Ali Emre Çakmakoğlu
  • 864
  • 2
  • 12
  • 24
1

I just add a DataTransformer without changing the array type of my roles attribute then I put this in my UserType :

use AppBundle\Form\DataTransformer\StringToArrayTransformer;

//...

$transformer = new StringToArrayTransformer();    
$builder->get('roles')->addModelTransformer($transformer);

And it works for me.

Bndev
  • 11
  • 1
1

I have your problem .. I solved this with this solution. I hope it helps you

this code work's on login and register form ...

user entity

class User {
    /**
     * @ORM\Column(type="array")
     */
    private $roles ;

    public function getRoles()
    {
        $roles = $this->roles;
         var_dump($roles);
        if ($roles != NULL) {
            return explode(" ",$roles);
        }else {
           return $this->roles;
        }
    }


  public function setRoles($roles)
    {
        $this->roles = $roles;
    }

UserType

 ->add('roles', ChoiceType::class, array(
            'attr' => array(
                'class' => 'form-control',
                'value' => $options[0]['roles'],
                'required' => false,
            ),
            'multiple' => true,
            'expanded' => true, // render check-boxes
            'choices' => [
                'admin' => 'ROLE_ADMIN',
                'user' => 'ROLE_USER',
            ]
        ))
pedram shabani
  • 1,654
  • 2
  • 20
  • 30