you can do something similar on UPDATING event that laravel fires when creating or updating a model..
Is it possible to make a mutator (setter) only for date attributes in Laravel?
I was thinking something like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class WorkHour extends Model
{
protected $fillable = [
'user_id',
'start_time',
'end_time'
];
protected $dates = ['start_time', 'end_time'];
public function user()
{
return $this->belongsTo(User::class);
}
// something like this:
public function setDatesAttribute($dates)
{
foreach ($dates as $date){
$this->attributes[$date] = Carbon::parse($date);
}
}
}
This of course doesn't work, but the main point here is that I have a lot of models with dates in it and with localized date in form request that looks like this "23.09.2017 22:12" I get an error on form submit (Invalid datetime format) so I need to have a setter to convert the date to be able to save it. So I created a setter for each date attribute in every model and that was a temporary fix and it works all fine. But I don't like it.
So is there a way to make one universal setter for $dates array (a setter to be applied on every attribute inside an array)?
This could then be extracted to a Trait or a Class to be able to apply it to mutate every date inside dates array for any model!
I got the validation error only because the field was empty so I added nullable to validation rule.
This is my final solution:
<?php
namespace App\Traits;
trait FormatDates
{
protected $databaseFormat = 'Y-m-d H:i:s';
/**
* Convert Model dates from Datepicker to date instance
* so it can be saved to DB
*
* @param $key
* @param $value
*/
public function setAttribute($key, $value)
{
if (!is_null($value) && strtotime($value)) {
$date = date($this->databaseFormat, strtotime($value));
parent::setAttribute($key, $date);
} else {
parent::setAttribute($key, $value);
}
}
}
and in Model to get the Carbon instances in views i just created $casts variable
protected $casts = [
'published_at' => 'datetime'
];
Please or to participate in this conversation.