Symfony 4 - 无法转换 属性 路径“[myDateTime]”的值:需要一个 \DateTimeInterface

Symfony 4 - Unable to transform value for property path "[myDateTime]": Expected a \DateTimeInterface

我想使用 Symfony 表单呈现日期时间选择器。

由于日期时间选择器只需要输入文本(因为它 returns 是一个简单的字符串),我决定使用 DataTransformers 表单将数据从日期时间转换为字符串,反之亦然。 但是当我尝试呈现我的页面时,我收到以下错误消息:

Unable to transform value for property path "[myDateTime]": Expected a \DateTimeInterface.

我的控制器class如下:

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class HomeController
 * @package App\Controller
 */
class HomeController extends Controller
{    
    /**
     * @Route("/test", name="form_test")
     */
    public function testForm(Request $request)
    {
        $data = ['myDateTime' => new \DateTime()];
        $builder = $this->createFormBuilder($data)
            ->add('myDateTime', DateTimeType::class, ['label' => 'My datetime']);

        $builder
            ->get('myDateTime')
            ->addModelTransformer(new DateTimeToStringTransformer(null, null, 'd/m/Y H:i'));

        $form = $builder->getForm();
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            dump($form->getData());
        }

        return $this->render('test.html.twig', [
            'form' => $form->createView(),
        ]);
    }
}

我的视图模板就是这么简单:

{% extends 'base.html.twig' %}

{% block body %}
    {{ form_start(form) }}
        {{ form_widget(form) }}
        <button class="btn btn-success">{{ button_label|default('Send') }}</button>
    {{ form_end(form) }}
{% endblock %}

为了呈现我的日期时间选择器,我使用了存储在 form/fields.html.twig:

中的表单主题
{% use "bootstrap_4_layout.html.twig" %}

{% block datetime_row %}
    <div class="form-group">
        {{ form_label(form) }}
        {{ form_errors(form) }}
        {{ form_widget(form) }}
        {{ form_help(form) }}
    </div>
{% endblock %}

{% block datetime_widget %}
    <div class="input-group date" id="{{ id }}" data-target-input="nearest">
        <input type="text" class="form-control datetimepicker-input" data-toggle="datetimepicker" data-target="#{{ id }}" {% if value %}value="{{ value|e('html_attr') }}"{% endif %}/>
        <div class="input-group-append" data-target="#{{ id }}" data-toggle="datetimepicker">
            <div class="input-group-text"><i class="fa fa-calendar"></i></div>
        </div>
    </div>
{% endblock datetime_widget %}

并将此主题添加到 twig.yaml 配置文件中:

twig:
    paths: ['%kernel.project_dir%/templates']
    debug: '%kernel.debug%'
    strict_variables: '%kernel.debug%'
    form_themes:
        - 'bootstrap_4_layout.html.twig'
        - 'form/fields.html.twig'

有没有人帮助我理解为什么这不起作用或我做错了什么?

为了让您的表单正常工作,您必须在 myDateTime 字段中使用 TextType 而不是 DateTimeType

$builder = $this->createFormBuilder($data)
        ->add('myDateTime', TextType::class, ['label' => 'My datetime']);

解释:

Symfony 默认为 DateTimeType 字段添加 DataTransformerChain 类型的 ViewTransformer。此转换器在 Form class 中的 normToView 函数内部调用,并需要 \DateTime class 的参数。但是,通过添加 DateTimeToStringTransformer 类型的 ModelTransformer,您已经将 myDateTime 字段的规范化值更改为字符串,这就是您收到错误的原因。

此外,即使您使用

,您的代码也无法正常工作

->addViewTransformer(new DateTimeToStringTransformer(null, null, 'd/m/Y H:i'));

而不是

->addModelTransformer(new DateTimeToStringTransformer(null, null, 'd/m/Y H:i'));

因为在这种情况下,DataTransformerChain 转换器在您添加的转换器之前被调用,您将得到相同的错误,这次来自 DateTimeToStringTransformer

您不需要 DateTimeToStringTransformer。删除此变压器。默认情况下,Symfony DateTimeType 需要一个 \DateTime 对象。

所以发生的事情是你的转换器正在将它转换为一个字符串,然后 DateTimeType 期待一个 DateTime 但它得到的是一个字符串所以它导致了这个错误。

您可以在此处阅读更多内容:https://symfony.com/doc/current/reference/forms/types/datetime.html#input