Symfony2 - array to string conversion error
Asked Answered
F

4

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  +
Flavourful answered 26/6, 2013 at 8:21 Comment(8)
please provide the full stack trace - otherwise nobody can see where the error has it's real sourceFederative
Full stack trace has been providedFlavourful
By the way it happens only when I set mapped to true (which is now)Flavourful
mapped true is the default value - you could ommit it. it's only necessary to put it to false if you don't want to add the values to the underlying entity of the form.Federative
what happens if you ommit "mapped" ?Federative
I know it's not necessary but it put it there just to set it to false (to check if the errors still appears). So how do I fix the problem?Flavourful
Exactly the same error as showed aboveFlavourful
could you add your entity please?Federative
B
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

Bradeord answered 27/6, 2013 at 13:8 Comment(3)
I will when I get enough reputation, for sureFlavourful
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.Marcomarconi
Your solution is true. However, it does not make sense. If your solution is based on losing data, it is not acceptable. @Flavourful 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.Prorate
L
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";}
Lyra answered 24/1, 2016 at 18:48 Comment(0)
L
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.

Lure answered 26/2, 2018 at 13:49 Comment(0)
D
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',
            ]
        ))
Dumbarton answered 27/5, 2018 at 17:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.