DataTransformer 中的 reverseTransform 不起作用


reverseTransform in DataTransformer doesn't work

>我创建了一个自定义表单字段类型"持续时间",以及 2 个字段"小时"和"分钟"

class DurationType extends AbstractType
{
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults([]);
    }
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('hours', new DurationSmallType(), [])
            ->add('minutes', new DurationSmallType(), [])
        ;
    }
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
    }
    public function getName()
    {
        return 'duration';
    }
}

持续时间小类型:

class DurationSmallType extends AbstractType
{
    public function getName()
    {
        return 'duration_small';
    }
}

两种类型的模板:

{% block duration_small_widget -%}
<div class="input-group" style="display: inline-block;width:100px;height: 34px;margin-right: 20px;">
    <input type="text" {{ block('widget_attributes') }} class="form-control" style="width:50px;" {% if value is not empty %}value="{{ value }}" {% endif %}>
    <span class="input-group-addon" style="height: 34px;"></span>
</div>
{%- endblock duration_small_widget %}
{% block duration_widget -%}
    {{ form_widget(form.hours) }}
    {{ form_widget(form.minutes) }}
{%- endblock duration_widget %}

在以分钟为单位保存的实体持续时间(作为整数)中,我在表单构建器中创建了一个数据转换器:

class EventType extends AbstractType
    {
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $dataTransformer = new DurationToMinutesTransformer();
        $builder
            ->add('name', NULL, array('label' => 'Название'))
            ->add('type', NULL, array('label' => 'Раздел'))
            ->add($builder
                ->create('duration', new DurationType(), array('label' => 'Продолжительность'))
                ->addModelTransformer($dataTransformer)
            )
        ->add('enabled', NULL, array('label' => 'Включено'));
    }
    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'TourConstructor'MainBundle'Entity'Event',
            'csrf_protection' => true,
            'csrf_field_name' => '_token',
            'intention' => 'events_token'
        ));
    }
    /**
     * @return string
     */
    public function getName()
    {
        return 'mybundle_event';
    }
}

持续时间到分钟变压器:

class DurationToMinutesTransformer implements DataTransformerInterface
{
    public function transform($value)
    {
        if (!$value) {
            return null;
        }
        $hours = ceil($value / 60);
        $minutes = $value % 60;
        return [
            "hours" => $hours,
            "minutes" => $minutes
        ];
    }
    public function reverseTransform($value)
    {
        if (!$value) {
            return null;
        }
        return $value["hours"]*60 + $value["minutes"];
    }
}

转换 - 工作,我在编辑字段中有小时和分钟,但反向转换不起作用,提交后我将持续时间字段作为数组。

符号错误:

Symfony'Component'Validator'ConstraintViolation
Object(Symfony'Component'Form'Form).children[duration].children[hours] = 3
Caused by:
Symfony'Component'Form'Exception'TransformationFailedException
Compound forms expect an array or NULL on submission.
Symfony'Component'Validator'ConstraintViolation
Object(Symfony'Component'Form'Form).children[duration].children[minutes] = 0
Caused by:
Symfony'Component'Form'Exception'TransformationFailedException
Compound forms expect an array or NULL on submission.

求你,帮帮我。

我发现错误,DurationSmallType 需要选项 compound=false,默认值为 true,symfony 尝试使用我的 2 字段作为内部形式。我从实体窗体中删除模型转换器并将其放置在持续时间类型中。

我的表单构建器的最终代码:

事件类型:

class EventType extends AbstractType
    {
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $dataTransformer = new DurationToMinutesTransformer();
        $builder
            ->add('name', NULL, array('label' => 'Название'))
            ->add('type', NULL, array('label' => 'Раздел'))
            ->add($builder
                ->create('duration', new DurationType(), array('label' => 'Продолжительность'))
                ->addModelTransformer($dataTransformer)
            )
        ->add('enabled', NULL, array('label' => 'Включено'));
    }
    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'TourConstructor'MainBundle'Entity'Event',
            'csrf_protection' => true,
            'csrf_field_name' => '_token',
            'intention' => 'events_token'
        ));
    }
    /**
     * @return string
     */
    public function getName()
    {
        return 'mybundle_event';
    }
}

持续时间类型:

class DurationType extends AbstractType
{
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'html5' => true,
            'error_bubbling' => false,
            'compound' => true,
        ));
    }
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('hours', new DurationSmallType(), [
                "label"=>"ч."
            ])
            ->add('minutes', new DurationSmallType(), [
                "label"=>"мин."
            ])
            ->addViewTransformer(new DurationToMinutesTransformer())
        ;
    }
    public function finishView(FormView $view, FormInterface $form, array $options)
    {
    }
    public function getName()
    {
        return 'duration';
    }
}

持续时间小类型:

class DurationSmallType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'compound' => false,
        ));
    }
    public function getName()
    {
        return 'duration_small';
    }
}