Symfony表单 - Choicetype - 错误 "数组转字符串转换"

6

我正在使用Symfony 3.4和FosUserBundle。为了包含角色,我自定义了注册表单:

<?php

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

现在在注册表单中通过2个新的复选框选择角色...但我想使用<select>标签来显示它。当我将expanded选项设置为false时,我会得到一个下拉选择框,但如果我将multiple选项设置为FALSE,我会收到一个错误:

Array to string conversion

有什么解决方法吗?

编辑:下面是堆栈跟踪:

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)

堆栈跟踪中是否有更多信息? - Matthew Usurp
你应该使用 'expanded' => false 和 'multiple' => true。 - Jasmin Mistry
1
@MatthewUsurp,我在我的第一个主题中添加了堆栈跟踪。 - Paolito75
如果我添加它,就会出现一个新错误:选项“empty_value”不存在。 - Paolito75
你有做过任何研究吗?你的问题看起来非常类似于这个 https://dev59.com/SGQm5IYBdhLWcg3w0Bu5 - Thai Duong Tran
显示剩余2条评论
3个回答

9
为了解决你的问题,你需要一个数据转换器,因为roles字段实际上是一个数组:
将数据转换器添加到你的FormType类中,连同roles字段一起添加,而不是在控制器中添加:
$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];
        }
));

6

2020 - Symfony 5.0.8:

在你的表单类型文件中:

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

2
发生的情况很正常:您的属性角色是一个字符串数组。在您的实体中,您可能会看到以下内容:
/**
 * @var array
 */
private $roles = [];

当你将选项 multiple => 'true' 放入 Symfony 表单中时,逻辑上讲,Symfony 表单会将其视为数组,并将数组的每个元素转换为字符串(它们已经是字符串了)。
另一方面,如果将 multiple => false 放入表单中,则会将数组视为单个选择,但实际上它不是这样的。
简而言之,您的模型中 roles 属性是一个字符串数组,但您尝试创建的表单将 roles 视为单个值,这造成了不一致性。
在您的情况下,您需要将 multiple => true 放入表单中。

如果您坚持想要multiple => false,我建议您查看答案,它恰好是您的问题。 - letibelim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接