Laravel: how to set date format on model attribute casting?
Asked Answered
P

8

51

I have in model:

protected $casts = [
    'date' => 'date',
];

Does laravel have some ability to set cast format, something like:

protected $casts = [
    'date' => 'date_format:d/m/yyyy',
];

?

EDITED

I tried this:

In model:

protected $dateFormat = 'm/d/Y';

protected $dates = ['driver_expiration', 'created_at', 'updated_at', 'deleted_at'];

protected $casts = [
    'driver_expiration'     => 'date',
];

I saved date(driver_expiration) as '01/012016' but date is saved 0000-00-00.

laravel documentation: https://laravel.com/docs/5.1/eloquent-mutators Tell us $dateFormat works only for timestamps ('created_at', 'updated_at', 'deleted_at')

Polyhydroxy answered 16/6, 2016 at 11:11 Comment(0)
N
48

Instead of casting a date format, you can use mutators to set the format you like:

For example, if your column was called date, you can add the following function to your model:

public function setDateAttribute( $value ) {
  $this->attributes['date'] = (new Carbon($value))->format('d/m/y');
}

The setDateAttribute is always in the format set[ColumnName]Attribute, using CamelCase. The date in the $this->attributes['date'] part must also match your actual column name in the table.

When you create or update a record in your database, the format will automatically be changed by the function above.

Note: You may need to add the use Carbon\Carbon statement to the top of your Model to use the Carbon library.

Take a look at other examples here.


UPDATE

Optionally, you can define a format for date columns using:

protected $dateFormat = 'Y-m-d';
Naarah answered 16/6, 2016 at 11:25 Comment(5)
I don't want 1000 mutators, and repeat code....array is more elegant and practical.Polyhydroxy
@Polyhydroxy also you can use models dateformat, there is no way to do this in casts by defaultLynn
@Polyhydroxy github.com/illuminate/database/blob/5.1/Eloquent/… here is proof, seems like casts using $dateFormat for formatingLynn
So much for "elegant and practical". Using mutators would have been much easier.Naarah
The last thing you want to do is clutter up your data model needless code. You can accomplish the same thing with casting.Frizzly
B
112

After laravel 5.6,

You can individually customize the format of Eloquent date and datetime casting:

protected $casts = [
    'birthday'  => 'date:Y-m-d',
    'joined_at' => 'datetime:Y-m-d H:00',
];

This format is used when the model is serialized to an array or JSON data

Biddy answered 25/5, 2018 at 18:47 Comment(3)
I have added above code in model and changed format to 'date:m-d-Y' but eloquent find method does return result in m-d-y. Please suggest.Tifanie
how can casting leave together with protected $dates carbon casting declaration?Usquebaugh
Doc is available here: Laravel 5.6+ or Laravel 6.x.Baccalaureate
N
48

Instead of casting a date format, you can use mutators to set the format you like:

For example, if your column was called date, you can add the following function to your model:

public function setDateAttribute( $value ) {
  $this->attributes['date'] = (new Carbon($value))->format('d/m/y');
}

The setDateAttribute is always in the format set[ColumnName]Attribute, using CamelCase. The date in the $this->attributes['date'] part must also match your actual column name in the table.

When you create or update a record in your database, the format will automatically be changed by the function above.

Note: You may need to add the use Carbon\Carbon statement to the top of your Model to use the Carbon library.

Take a look at other examples here.


UPDATE

Optionally, you can define a format for date columns using:

protected $dateFormat = 'Y-m-d';
Naarah answered 16/6, 2016 at 11:25 Comment(5)
I don't want 1000 mutators, and repeat code....array is more elegant and practical.Polyhydroxy
@Polyhydroxy also you can use models dateformat, there is no way to do this in casts by defaultLynn
@Polyhydroxy github.com/illuminate/database/blob/5.1/Eloquent/… here is proof, seems like casts using $dateFormat for formatingLynn
So much for "elegant and practical". Using mutators would have been much easier.Naarah
The last thing you want to do is clutter up your data model needless code. You can accomplish the same thing with casting.Frizzly
F
12

Just add to the model:

protected function asDateTime($value)
{
    return parent::asDateTime($value)->format('d/m/y');
}

this Eloquent's method originally return a Carbon instance, so you can get that instance and calls to its format() method. If you wish to apply this solution to all models, just create a new class extended from Eloquent, and put this method there, so then you can extend the models from this new class.

Friction answered 6/9, 2017 at 0:28 Comment(3)
Out of all the answers in this, its the only one that works (for me) with Laravel 8Defrost
Thanks for this answer! Best way to convert format/timezone without accessors or any custom functionsFelonry
also it work' on laravel 10 with adding protected $casts variablePiers
B
5

For me, I just put the following code in my Model it will format all dates

protected function serializeDate($date)
{
    return $date->format('Y-m-d H:i:s');
}
Bennink answered 17/8, 2022 at 11:20 Comment(0)
P
2

I create new model property:

protected $datesConvert = ['driver_expiration'];

And then I updated my base model like :

public function save(array $options = [])
{
    if(isset($this->datesConvert)){
        foreach($this->datesConvert as $date){
            $this->attributes[$date] = \Carbon\Carbon::createFromFormat('d/m/Y', $this->attributes[$date])->format('Y-m-d');
        }
    }

    parent::save($options);

}

public function getAttribute($key)
{
    $value = parent::getAttribute($key);

    if(isset($this->attributes[$key])){
        if(isset($this->datesConvert)  &&  in_array($key, $this->datesConvert)){
            $value = \Carbon\Carbon::createFromFormat('Y-m-d', $value)->format('d/m/Y');
        }

    }

    return $value;
}

and this solution works for me. Code can be moved to trait. Format can be put in $datesConvert Format = 'd/m/Y';

Polyhydroxy answered 16/6, 2016 at 12:15 Comment(0)
O
1

Casts are not affected by the Collection object. It's used for json and array formats. If you need an individual cast that you can use

 $user->date->format('m-d-Y');
Overwhelming answered 27/9, 2019 at 7:3 Comment(0)
S
0

Try this:

//Note: Add this Carbon library at the top of your Model. 
use Carbon\Carbon
    
public function getDateAttribute($date)
        {
            return $this->attributes['date'] = Carbon::parse($date)->format('d/m/Y');
        }
Saddlebag answered 25/6, 2022 at 2:20 Comment(0)
C
0

Laravel 10.x

in model

use Illuminate\Database\Eloquent\Casts\Attribute;

protected function createdAt(): Attribute
{
    return Attribute::make(
        get: fn ($value, $attributes) => Carbon::create($value)->format(m/d/Y")
    );
}
Crinkumcrankum answered 24/2, 2023 at 8:15 Comment(1)
it is not practical to use mutators if you have maaaaany dates to castsPiers

© 2022 - 2024 — McMap. All rights reserved.