Symfony主义DateTime表单TimeType

时间:2018-07-07 18:23:18

标签: forms symfony datetime symfony4

场景

我的start类型的实体中有endDateTime字段。

/**
 * @ORM\Column(type="datetime")
 * @var \DateTime
 */
private $start;

/**
 * @ORM\Column(type="datetime", nullable=true)
 * @var \DateTime
 */
private $end;

我只想修改这些值的时间,所以我用这样的字段声明构建了一个表单:

->add('start', TimeType::class, [
    'widget' => 'single_text',
])
->add('end', TimeType::class, [
    'widget' => 'single_text',
])

样本值

更新前这些字段的样本值(格式:'Y-m-d h:i:s'):2018-07-01 17:30:00

表单输入

17:50

预期结果

2018-07-01 17:50:00

实际结果

1970-01-01 17:50:00

有没有一种方法可以使用表单仅显示和修改DateTime对象的时间部分,而无需触摸日期部分?

1 个答案:

答案 0 :(得分:1)

理论上,您将需要编写自己的数据转换器,该转换器将接受您的输入,验证特定字段并将其与现有数据合并。您还需要解决一个极端的情况,即有人提交了time,但当时的现有数据为空。

从外观上看,目前没有满足您要求的变压器,但是编写您自己的变压器相对容易。我看到的问题是,您将需要使转换器知道模型数据并将合并的数据与现有数据合并。对我来说,这将是不良设计和明显违反责任的标志。

如果您仍然愿意,可以查看以下内容:

How to Use Data Transformers

和现有的日期转换器之一:

DateTimeToStringTransformer

但是,我的方法是监听特定字段上的SUBMIT事件并拦截提交的数据。

这是我设法快速编写的示例:

$inData = [
    'start_date' => new \DateTime(),
];

// Shows local date: 2018-07-07 23:28
dump($inData);

$form = $this->createForm(PartialTimeType::class, $inData);

$form->submit([
    'start_date' => '23:50',
]);

$outData = $form->getData();

// Should show 2018-07-07 23:50
dump($outData);

PartialTimeType:

$builder
    ->add('start_date', TimeType::class, [
        'label' => 'Start time',
        'widget' => 'single_text'
    ]);

$builder->get('start_date')->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
    /** @var \DateTime $modelData */
    $modelData = $event->getForm()->getData();
    /** @var \DateTime $data */
    $data = $event->getData();

    $data->setDate(
        (int)$modelData->format('Y'),
        (int)$modelData->format('m'),
        (int)$modelData->format('d')
    );
});

我确信您可以编写自己的TimeType扩展名,该扩展名将这种行为封装为box ...

希望这对您有帮助...