Reputation: 45
Scenario
I have start
and end
fields in my entity of type DateTime
.
/**
* @ORM\Column(type="datetime")
* @var \DateTime
*/
private $start;
/**
* @ORM\Column(type="datetime", nullable=true)
* @var \DateTime
*/
private $end;
I want to modify only the time of these values, so I build a form with fields declaration like that:
->add('start', TimeType::class, [
'widget' => 'single_text',
])
->add('end', TimeType::class, [
'widget' => 'single_text',
])
Sample values
Sample value of these fields before update are (formatted: 'Y-m-d h:i:s
'): 2018-07-01 17:30:00
Form input
17:50
Expected result
2018-07-01 17:50:00
Actual result
1970-01-01 17:50:00
Is there a way to render and modify only the time part of the DateTime object with the form without touching the date part?
Upvotes: 0
Views: 2321
Reputation: 20191
In theory you would need to write your own data transformer which would take your input, validate and merge specific fields with existing data. You would also need to cover an edge case where someone submits the time
, but existing data is empty at the time.
From the looks of it, there is currently no existing transformer which meets your requirements, but it would be relatively easy to write your own. The problem that I see with this is that you will need to make your transformer aware of model-data and merge incoming data with existing one. For me, this would be sign of bad design and clear violation of responsibility.
If you're still up for it, you can check out these:
And one of the existing date transformers:
However, my approach would be to listen to SUBMIT
event on a particular field and intercept the submitted data.
This is an example I managed to write quickly:
$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')
);
});
I am sure that you could write your own extension of TimeType
which encapsulates this behavior our of box...
Hope this helps...
Upvotes: 1