如何正确地将日期转换为字符串并以 symfony 形式返回,以便可以使用日期选择器

how to properly transform date to string and back in symfony form so can use date picker

在我的 Symfony 4 应用程序中,我有一个包含日期类型字段的实体。默认情况下,Symfony 将其呈现为一组 select 框,代表月、日、年。我已将其更改为文本小部件,以便我可以使用 jQuery UI 日期选择器。

但是我 运行 在尝试提交表单时遇到了问题。

这是我实体上的字段:

/**
 * @ORM\Column(type="date")
 */
private $start_date;

这是我显示字段的方式:

$builder->add('start_date', DateType::class, [
                'widget' => 'single_text',

                // prevents rendering it as type="date", to avoid HTML5 date pickers
                'html5' => false,

                // adds a class that can be selected in JavaScript
                'attr' => ['class' => 'js-datepicker'],
            ])

我的页面上有 jquery 和 jqueryui,这允许显示日期选择器。

以下是我目前正在尝试将日期转换为字符串的方法,反之亦然。目前,我只是尝试使用硬编码日期,当然,一旦我知道我在做什么,我就会更改它。

$builder->get('start_date')
->addModelTransformer(new CallbackTransformer(
    function ( $dateAsString ) {
        return new \DateTime('2019-01-01');
    },
    function ( $dateAsDate ) {
        return '2019-01-01';
    }
));

提交表单产生此错误: 给定 "DateTimeInterface"、"string" 类型的预期参数。

有没有人知道如何在我的实体中将日期存储为日期类型,同时在我的表单中将其显示为字符串?

我邀请您查看 documentation of DateType。您会发现您可以根据 input 选项以多种格式存储日期:

  • 字符串(例如 2011-06-05)
  • datetime(一个 DateTime 对象)
  • datetime_immutable(一个 DateTimeImmutable 对象)
  • 数组(例如 ['year' => 2011,'month' => 06,'day' => 05])
  • 时间戳(例如 1307232000)

这是您实体中的基础 model value。在您的示例中,您必须选择默认值 datetime

您为 widget 选项做出了正确的选择 - single_text。不要忘记设置一个正确的format。这是view value

在您的情况下,您不需要编写自己的数据转换器。 Symfony 会负责将 model value 转换为 view value,反之亦然。它通过 normalised value:

使用
`model data`(string, datetime, timestamp, etc.) -> `norm data` (`DateTime`) -> `view data` (string for widget=single_text, array for widget=choice)

`view data` (string for widget=single_text, array for widget=choice) -> `norm data` (`DateTime`) -> `model data`(string, datetime, timestamp, etc.)

虽然 view datamodel data 的格式不同,但 norm data 的格式始终相同 - DateTime。您添加的模型转换器返回 string 以设置为规范化数据。这就是你出错的原因。

您可以将预定义格式添加到您的表单生成器中,就像这样

                'widget' => 'single_text',
                //default format of the date 
                'format' => 'yyyy-MM-dd',

                // prevents rendering it as type="date", to avoid HTML5 date pickers
                'html5' => false,

                // adds a class that can be selected in JavaScript
                'attr' => ['class' => 'js-datepicker'],
            ])

在这种情况下您不需要转换器,formbuilder 会处理它。