Reputation: 53
I'm having problems getting Laravel to cast a custom attribute as a Carbon
date. Here's an example model:
class Organisation extends Model
{
protected $dates = [
'my_date'
];
public function getMyDateAttribute()
{
return "2018-01-01 00:00:00";
}
}
I'd expect my_date
to be cast to a Carbon
date however if I do dd($organisation->my_date)
it just returns the date as a string.
I've seen people suggest to just return a Carbon
instance from the custom attribute, and this partially works, the my_date
attribute is availabe as a Carbon
instance within the application, however if you then return the model as Json you end up with:
{
"name": "Big Business",
"my_date": {
"date": "2018-01-01 00:00:00.000000",
"timezone_type": 3,
"timezone": "Europe/London"
}
}
Instead of the desired:
{
"name": "Big Business",
"my_date": "2018-01-01 00:00:00"
}
Has anyone else come across this and if so have you found a solution?
Upon further investigation I've tracked down the problem (but I don't have a solution yet). When you return an Eloquent model the __toString
magic method which runs the toJson
method and as you trace down the chain it serializes any Carbon dates in the $dates
variable. It also completely skips over this serialization for mutated attributes, which is what I'm seeing.
I need to find a way to seralize mutated attributes that return a Carbon
date when __toString
is called.
Upvotes: 0
Views: 2874
Reputation: 2156
You if your model represents a table, you can change the data type to timestamp and laravel will put that attribute into a carbon object.
Once the attribute is a carbon object, you can change the format in the blade view.
{{ $organisation->mydate->format('Y-m-d') }}
If either cannot change the data type, or you need to a default format different from a timestamp you can use the 'cast' eloquent model property.
class Organisation extends Model{
protected $cast = [
'mydate'=>'datetime:Y-m-d H:i:s'
];
}
Casting the attribute effectively works the same as an accessor that wraps the date value with a carbon object. This is much cleaner way to write it, however.
As far as timezone is concerned, you should look to change that in the config/app.php file.
Here is the documentation.... https://laravel.com/docs/5.8/eloquent-mutators#attribute-casting
Upvotes: 0
Reputation: 1153
edit your Organization
model to this:
use Carbon\Carbon;
class Organisation extends Model
{
public function getMyDateAttribute($value)
{
//you can manipulate the date here:
$date = Carbon::parse($value,config('timezone'));
return $date;
}
}
Upvotes: 2