简体   繁体   中英

Laravel dates on form model binding

I'm using Laravel 5.1

I got a model:

class ExampleModel extends Model {

    // ....
    protected $dateFormat = 'Y.m.d';
    protected $dates = ['first_date', 'second_date'];

    // ...
}

So when I'm indexing ExampleModel elements, the date format is correct (ex 2015.07.31)

But on an edit form it uses the default format: 2015-07-31 00:00:00

I'm using Form::model() binding.

I know I could use getFirstDateAttribute() but it's not the solution I'm looking for. Because it's not elegant at all and once I defined the $dates array, it should work automatically in every case.

So is it a bug maybe? Or am I doing something wrong?

I solved my problem by overriding Carbon's default date format:

Carbon\Carbon::setToStringFormat('Y.m.d');

But Kelly's answer is much better and more elegant, I just post this one as well, maybe someone will find this useful once.

I've never done this before, but it seems to work on a basic example I put together. Note that I'm just calling the toArray method on the model in the form opening 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 that the dateFormat property determines the date format when the object is cast to json or an array.

I don't fully advise this as a fix because when you update the core you'll lose this fix, but maybe this should be posted as a pull request to Laravel's next version.

In \\Illuminate\\Database\\Eloquent\\Concerns\\HasAttributes update the asDate function as follows. As you can see from the comments the asDate function still returns a timestamp even though 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 a date from the model (note I'm differentiating between a date and datetime). Then use the casts variable to cast your variable to date format.

protected $casts = [
    'start_date' => 'date',
    'end_date' => 'date'
  ];
  protected $dateFormat =  'Y-m-d';

The $dates variable cannot differentiate between a date and a datetime.

UPDATE The real problem is the form model binding skips the helper function of the FormBuilder class. As you can see if you inspect \\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);
}

It is correctly formatting date to 'Ymd' as specified in HTML5 spec. However at this point $value is actually null. So you have to update the generic 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 There is no need to update vendor code. Check out FormModelAccessors

https://laravelcollective.com/docs/5.2/html#form-model-binding

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM