mongodb / laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel (Moloquent)
https://www.mongodb.com/docs/drivers/php/laravel-mongodb/
MIT License
7k stars 1.43k forks source link

Updating a date field using update([]) does not convert it to mongo date. #2177

Open fidan-mkdir opened 3 years ago

fidan-mkdir commented 3 years ago

Description:

Updating documents with the ->update() method saves Carbon dates as Object instead of Date in the database. Doing the same using ->save() on a model works fine. Yes, the models have the property registered as a date in the $dates array.

Steps to reproduce

  1. Create model with property 'end_date'. Add property to $dates array on the model.
  2. Create date $date = Carbon::parse('2021-01-08 10:00');
  3. Run query: Model::where('match', true)->update(['end_date' => $date]);
  4. Check db.

Expected behaviour

The end_dateshould be saved as a field of type Date instead of Object image

Actual behaviour

end_date is saved as object image

Additionally, if you were to do ->update(['end_date' => $date->toIso8601String()]) the date would be saved as a String field

divine commented 3 years ago

Hello,

That's correct behavior. You're updating the field which is saved as a string.

If you need to save it as a date field then typecast it to https://github.com/jenssegers/laravel-mongodb/blob/ae864fbca560419cca65b503c5da0a1315bf177a/src/Jenssegers/Mongodb/Eloquent/Model.php#L92

Thanks!

fidan-mkdir commented 3 years ago

But why isn't it consistent? If I do: $model->end_date = $date; $model->save();

then it is saved as date.

divine commented 3 years ago

But why isn't it consistent? If I do: $model->end_date = $date; $model->save();

then it is saved as date.

Yes, should be same but not taking care.

Thanks!

darcyrailip commented 2 years ago

Just chiming in that I would agree the update() behaviour should obey the $dates fields.

$model = new Model();
Model::update([
    'date_field' => Carbon::now()
]);

Should be functionally the same as:

$model = new Model();
$model->date_field = Carbon::now();
$model->save();
Murked commented 1 year ago

Just run into this problem now, after trying $dates to no success, it seems $casts did the trick.

protected $casts = [ 'date_field' => 'datetime' ];

Then it works as expected!

alcaeus commented 1 year ago

Just run into this problem now, after trying $dates to no success, it seems $casts did the trick.

That mainly depends on the version you're using. For the upcoming 4.0 release, compatibility with Laravel 10 means that the $dates property isn't relevant anymore and any date fields are handled through $casts like other fields are already. I presume that the current stable 3.9 release still has the same problem, but we won't be making changes to that version anymore.