具有选择形式的 Symfony DataTransformers

问题描述 投票:0回答:1

我制作了一个 DataTransformer,它基本上不是针对提交的可用选择。

我的问题是我的变压器收到

['INFO' => 'INFO', 'WARN' => 'WARN']
[0 => 'INFO', 1 => 'WARN']
。当所有复选框均未选中(又称选择的模型数据为 ['INFO'、'WARN'])并且我选中任何复选框并提交表单时,通常会发生这种情况。

我使用的是 Symfony 2.6.6。

这是表格:

$choice = $builder->create('choice', 'choice', array(
    'choices' => array(
        'INFO' => 'INFO',
        'WARN' => 'WARN'
    ),
    'multiple' => true,
    'expanded' => true
);
$choice->addModelTransformer(new ReverseChoiceFieldTransformer($choice));
$builder->add($choice);

这是变压器:

class ReverseChoiceFieldTransformer implements DataTransformerInterface {
    private $choices;

    public function __construct(FormBuilderInterface $fbi) {
        $this->choices = $fbi->getOption('choices');
    }

    public function transform($value) {
        return $this->reverseTransform($value);
    }

    public function reverseTransform($value) {
        return $value === '' ? null : array_diff_key($this->choices, $value);
    }
}
php symfony symfony-forms
1个回答
3
投票

我不太清楚为什么在这种情况下你要使用

DataTransformer
。它们用于简化复杂的表单,其中输入的表单数据必须转换为其他内容。您可能想查看有关数据转换器的 Symfony 官方文档

此外,您的

ReverseChoiceFieldTransformer
类未正确实现。
transform
方法旨在将
Object
转换为简单类型,如
string
int
等,稍后以
ViewData
的形式显示。相反,
reverseTransform
方法用于将数据从简单类型反向转换回相同的
Object
。你可以在下图中看到这一点(取自 Symfony 官方文档)

Model and View Transformers

话虽如此,我相信您解决问题的方法可能是错误的。如果您在控制器或表单事件中执行此操作可能会更好。以下是如何获取控制器类中的数据的示例:

// MyFormType
class MyFormType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('choice', 'choice', array(
            'choices' => array(
                'INFO' => 'Info label',
                'WARN' => 'Warn label',
                'CRIT' => 'Crit label',
            ),
            'multiple' => true,
            'expanded' => true,
            'required' => false,
            'mapped'   => false
        ))
        ->add('submit', 'submit', array(
            'attr' => array('class' => 'save'),
        ));;
    }

    public function getName() {
        return "my_form";
    }
}

// MyController
class MyController extends Controller {
    /**
     * @Route("/test")
     * @Template()
     */
    public function testAction(Request $request) {
        $form = $this->createForm(new MyFormType());
        $form->handleRequest($request);

        if($form->isValid())
        {
            // Get selected
            $selectedChoices = $form->get('choice')->getData();
            // outputs the checked values, i.e.
            // array (size=2)
            //    0 => string 'INFO' (length=4)
            //    1 => string 'WARN' (length=4)

            // All choices with their labels
            $allChoices = $form->get('choice')->getConfig()->getOption('choices');
            // outputs all choices, i.e.
            // array (size=3)
            //   'INFO' => string 'Info label' (length=10)
            //   'WARN' => string 'Warn label' (length=10)
            //   'CRIT' => string 'Crit label' (length=10)

            // All unchecked choices. Pay attention to the difference
            // in the arrays.
            $unchecked = array_diff(array_keys($allChoices), array_values($selectedChoices));

        }

        return array('form' => $form->createView());
    }
}


跟进评论:

你说对了一部分。

transform
方法接收用于构建表单的模型数据,而
reverseTransform
方法接收提交给表单的数据。尽管在您的情况下,两种情况下收到的数据都是
array
,但
array
本身包含不同的数据结构:

  1. transform
    将会收到:

    array (
        'INFO' => 'Info label',
        'WARN' => 'Warn label',
        'CRIT' => 'Crit label'
    )
    
  2. reverseTransform
    将收到选中的选项,即:

    array (
        0 => 'INFO',
        1 => 'CRIT'
    )
    


虽然,如果这可以通过 FormEvents 完成,我会选择控制器或研究,但以下代码应该可以完成工作:

class ReverseChoiceFieldTransformer implements DataTransformerInterface {
    private $choices;

    public function __construct(FormBuilderInterface $fbi) {
        $this->choices = $fbi->getOption('choices');
    }

    /**
     * The received data from the FormBuilder will be passed "AS IS"
     *
     * @param mixed $value
     * @return mixed
     */
    public function transform($value) {
        return $value;
    }

    /**
     * The received data from the submitted from will be modified. Doing
     * $form->get('choice')->getData() in the controller will return only
     * the unselected choices.
     *
     * @param mixed $value
     * @return null|array
     */
    public function reverseTransform($value) {
        return $value === '' ? null : array_diff(array_keys($this->choices),array_values($value));
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.