我想使用Symfony表单呈现日期时间选择器。
由于日期时间选择器只需要输入文本(因为它返回一个简单的字符串),我决定使用表格DataTransformers将数据从datetime转换为字符串,反之亦然。但是当我尝试渲染我的页面时,我收到以下错误消息:
无法转换属性路径“[myDateTime]”的值:预期\ DateTimeInterface。
我的Controller类如下:
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'
有没有人帮助我理解为什么这不起作用或我做错了什么?
为了让你的表单正常工作,你必须使用TextType
而不是DateTimeType
为你的myDateTime
字段:
$builder = $this->createFormBuilder($data)
->add('myDateTime', TextType::class, ['label' => 'My datetime']);
说明:
Symfony默认为ViewTransformer
字段添加DataTransformerChain
类型的DateTimeType
。这个变换器在normToView
类中的Form
函数内部调用,并期望\DateTime
类的参数。但是,通过添加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
。删除此Transformer。默认情况下,Symfony DateTimeType
需要一个\DateTime
对象。
所以发生的事情是你的变换器正在将它转换为一个字符串,然后DateTimeType
期待一个DateTime
,但是它得到一个字符串,所以它导致了这个错误。
你可以在这里阅读更多:https://symfony.com/doc/current/reference/forms/types/datetime.html#input