Laravel dates on model binding
I am using Laravel 5.1
I have a model:
class ExampleModel extends Model {
// ....
protected $dateFormat = 'Y.m.d';
protected $dates = ['first_date', 'second_date'];
// ...
}
So when I index the elements of the ExampleModel the date format is correct (ex 2015.07.31)
But in the edit form, it uses the default format: 2015-07-31 00:00:00
I am using anchor Form::model()
.
I know I can use it getFirstDateAttribute()
, but this is not the solution I am looking for. Since it is not elegant at all, and once I have defined an array $dates
, it should work automatically in every case.
So maybe this is a mistake? Or am I doing something wrong?
source to share
I've never done this before, but it seems to work with a basic example I put together. Note that I am just calling a method toArray
on the model in the form open tag.
{!! Form::model($exampleModel->toArray(), ['route' => ['example-models.update', $exampleModel->id]]) !!}
{!! Form::label('first_date', 'First Date') !!}
{!! Form::text('first_date') !!}
{!! Form::close() !!}
The docs say the property dateFormat
defines the date format when the object is passed to json or array.
source to share
I do not fully recommend this as a fix, because when you update your kernel you will lose this fix, but perhaps this should be posted as a pull request to the next Laravel version.
In \ Illuminate \ Database \ Eloquent \ Concerns \ HasAttributes updates the asDate function as follows. As you can see from the comments, the asDate function still returns the timestamp even if it's 00:00:00.
/**
* Return a timestamp as DateTime object with time set to 00:00:00.
*
* @param mixed $value
* @return \Illuminate\Support\Carbon
*/
protected function asDate($value)
{
$date = $this->asDateTime($value)->startOfDay();
$date->setToStringFormat($this->getDateFormat());
return $date;
}
This allows you to control the format of the date from the model (note that I differentiate between date and date and time). Then use the casts variable to convert your variable to date format.
protected $casts = [
'start_date' => 'date',
'end_date' => 'date'
];
protected $dateFormat = 'Y-m-d';
The variable $ date cannot distinguish between date and date and time.
UPDATE The real problem is that binding to the model form is missing the FormBuilder class helper function. As you can see if you are checking \ Collective \ Html \ FormBuilder :: date
/**
* Create a date input field.
*
* @param string $name
* @param string $value
* @param array $options
*
* @return \Illuminate\Support\HtmlString
*/
public function date($name, $value = null, $options = [])
{
if ($value instanceof DateTime) {
$value = $value->format('Y-m-d');
}
return $this->input('date', $name, $value, $options);
}
Formats the date correctly before 'Ym-d' as stated in the HTML5 spec. However, at this point, the value of $ is effectively null. Therefore, you need to update the general input function.
/**
* Create a form input field.
*
* @param string $type
* @param string $name
* @param string $value
* @param array $options
*
* @return \Illuminate\Support\HtmlString
*/
public function input($type, $name, $value = null, $options = [])
{
...
//$value is null here
if (! in_array($type, $this->skipValueTypes)) {
//$value is fetched based on hierarchy set by
$value = $this->getValueAttribute($name, $value);
//necessary duplicate code to format date value
if ($type == 'date' && $value instanceof DateTime) {
$value = $value->format('Y-m-d');
}
}
...
}
UPDATE No need to update vendor code. Check FormModelAccessors
https://laravelcollective.com/docs/5.2/html#form-model-binding
source to share