Reputation: 1280
I'm fairly new to Symfony2 and setting up a form to input datetime data into a MySQL database via doctrine, but I'm getting the following error:
The form's view data is expected to be of type scalar, array or an instance of \ArrayAccess, but is an instance of class DateTime. You can avoid this error by setting the "data_class" option to "DateTime" or by adding a view transformer that transforms an instance of class DateTime to scalar, array or an instance of \ArrayAccess.
When I try the suggested array('data_class' => 'dateTime')
setting for the field but i get the following in a cached twig template:
Catchable Fatal Error: Object of class DateTime could not be converted to string in
I've tried a few things to get this to work also but nothing seems to work!
In my entity it's declared as the following:
/**
* @var \DateTime
*
* @ORM\Column(name="my_date", type="datetime", nullable=false)
* @Assert\Date()
*/
private $myDate;
and as a hidden field in my form:
$form = $this->createFormBuilder($myClass)
->add('myDate', 'hidden')
The reason for it being hidden is because the values are added via a javascript multistage form. Can anyone sine some light on what the issue could be, or how I go about solving it? Should I change my entity settings to 'strings'?
Thanks.
Upvotes: 3
Views: 6328
Reputation: 2949
The simplest solution would be to create a date field and hide it with css
$form = $this->createFormBuilder($myClass)
->add('myDate','date',array( 'attr'=>array('style'=>'display:none;')) )
You will keep the javascript object date and it will be persisted as date in database
Upvotes: -1
Reputation: 41934
The hidden file type is just a text field which is hidden.
This means that, in order to render the widget, it just uses the simple widget template (see include statement in hidden_widget.html
):
<input type="<?php echo isset($type) ? $view->escape($type) : 'text' ?>" <?php echo $view['form']->block($form, 'widget_attributes') ?><?php if (!empty($value) || is_numeric($value)): ?> value="<?php echo $view->escape($value) ?>"<?php endif ?> />
As you can see it just echo's the value you passed to the field (the escape function does not to any important things). There is the problem: You passed a DateTime
class as value, not a string. Even though you specified you passed a DateTime
class, it's still not changing the value and it just tries to convert the DateTime
object into a string.
That isn't possible.
That's what currently happends. Now, let's move onto how to get it fixed. The data it tries to render ($value
) is actually called the view data (as you see where the variable is defined). In the current situation, the view data is equal to the Form::$viewData property (see the ->getViewData()
definition). This property is defined previously by the ->normToView()
method (see the $viewData
definition).
As you can see in the ->normToView()
method, it runs the view transformers if available:
foreach ($this->config->getViewTransformers() as $transformer) {
$value = $transformer->transform($value);
}
So in order to convert the DateTime
object to a string, we have to use a View transformer. Now, let's take a look at the available data transformers. We are very lucky as there is a DateTimeToStringTransformer
:
/**
* Transforms between a date string and a DateTime object
*
* @author Bernhard Schussek <[email protected]>
* @author Florian Eckerstorfer <[email protected]>
*/
class DateTimeToStringTransformer extends BaseDateTimeTransformer
{
That's just what we needed!
Now, let's register this data transformer as a view transformer to the hidden
field:
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
// ...
$builder = $this->createFormBuilder($myClass);
$builder->add(
$builder->create('myDate', 'hidden')
->addViewTransformer(new DateTimeToStringTransformer())
);
And after you've done this, the form should be correctly generated. And because, almost everything in the form is symmetric, the transformer also works from string to datetime, meaning that your code only uses the DateTime
object!
Upvotes: 13
Reputation: 3188
For manipulate date in form, you must use datetime, date or time form types, because thie types have a datetime view transformer.
So, in rendering form, all data`s must be scalar type.
If your want use datetime object in hidden field, you must use custom view transformer, because date time object not have a method *__toString* for convert value to string, and your can't reverse transform to datetime object.
For create custom view transformer, you can see documentation in Symfony 2 site.
trasnform - Transform datetime object to string value, and this value has been in input. reverseTransform - Transform value (string type) from input to datetime object.
P.S. As default your can use DateTimeToStringTransformer from Symfony Form package.
Upvotes: 0