Skip to content

Commit 2ea1a7c

Browse files
committed
Update handling of dates for Laravel 10
1 parent 452a0bb commit 2ea1a7c

File tree

5 files changed

+77
-20
lines changed

5 files changed

+77
-20
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,6 @@ use Jenssegers\Mongodb\Eloquent\SoftDeletes;
256256
class User extends Model
257257
{
258258
use SoftDeletes;
259-
260-
protected $dates = ['deleted_at'];
261259
}
262260
```
263261

@@ -279,7 +277,7 @@ use Jenssegers\Mongodb\Eloquent\Model;
279277

280278
class User extends Model
281279
{
282-
protected $dates = ['birthday'];
280+
protected $casts = ['birthday' => 'datetime'];
283281
}
284282
```
285283

src/Eloquent/Model.php

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@
22

33
namespace Jenssegers\Mongodb\Eloquent;
44

5+
use function array_key_exists;
56
use DateTimeInterface;
7+
use function explode;
68
use Illuminate\Contracts\Queue\QueueableCollection;
79
use Illuminate\Contracts\Queue\QueueableEntity;
10+
use Illuminate\Contracts\Support\Arrayable;
811
use Illuminate\Database\Eloquent\Model as BaseModel;
912
use Illuminate\Database\Eloquent\Relations\Relation;
1013
use Illuminate\Support\Arr;
1114
use Illuminate\Support\Facades\Date;
1215
use Illuminate\Support\Str;
16+
use function in_array;
1317
use Jenssegers\Mongodb\Query\Builder as QueryBuilder;
1418
use MongoDB\BSON\Binary;
1519
use MongoDB\BSON\ObjectID;
1620
use MongoDB\BSON\UTCDateTime;
21+
use function uniqid;
1722

1823
abstract class Model extends BaseModel
1924
{
@@ -94,7 +99,7 @@ public function fromDateTime($value)
9499
$value = parent::asDateTime($value);
95100
}
96101

97-
return new UTCDateTime($value->format('Uv'));
102+
return new UTCDateTime($value);
98103
}
99104

100105
/**
@@ -191,13 +196,14 @@ public function setAttribute($key, $value)
191196
$value = $builder->convertKey($value);
192197
} // Support keys in dot notation.
193198
elseif (Str::contains($key, '.')) {
194-
if (in_array($key, $this->getDates()) && $value) {
195-
$value = $this->fromDateTime($value);
196-
}
199+
// Store to a temporary key, then move data to the actual key
200+
$uniqueKey = uniqid($key);
201+
parent::setAttribute($uniqueKey, $value);
197202

198-
Arr::set($this->attributes, $key, $value);
203+
Arr::set($this->attributes, $key, $this->attributes[$uniqueKey] ?? null);
204+
unset($this->attributes[$uniqueKey]);
199205

200-
return;
206+
return $this;
201207
}
202208

203209
return parent::setAttribute($key, $value);
@@ -222,13 +228,6 @@ public function attributesToArray()
222228
}
223229
}
224230

225-
// Convert dot-notation dates.
226-
foreach ($this->getDates() as $key) {
227-
if (Str::contains($key, '.') && Arr::has($attributes, $key)) {
228-
Arr::set($attributes, $key, (string) $this->asDateTime(Arr::get($attributes, $key)));
229-
}
230-
}
231-
232231
return $attributes;
233232
}
234233

@@ -515,4 +514,62 @@ public function __call($method, $parameters)
515514

516515
return parent::__call($method, $parameters);
517516
}
517+
518+
/**
519+
* Add the casted attributes to the attributes array.
520+
*
521+
* @param array $attributes
522+
* @param array $mutatedAttributes
523+
* @return array
524+
*/
525+
protected function addCastAttributesToArray(array $attributes, array $mutatedAttributes)
526+
{
527+
foreach ($this->getCasts() as $key => $castType) {
528+
if (! Arr::has($attributes, $key) || Arr::has($mutatedAttributes, $key)) {
529+
continue;
530+
}
531+
532+
$originalValue = Arr::get($attributes, $key);
533+
534+
// Here we will cast the attribute. Then, if the cast is a date or datetime cast
535+
// then we will serialize the date for the array. This will convert the dates
536+
// to strings based on the date format specified for these Eloquent models.
537+
$castValue = $this->castAttribute(
538+
$key, $originalValue
539+
);
540+
541+
// If the attribute cast was a date or a datetime, we will serialize the date as
542+
// a string. This allows the developers to customize how dates are serialized
543+
// into an array without affecting how they are persisted into the storage.
544+
if ($castValue !== null && in_array($castType, ['date', 'datetime', 'immutable_date', 'immutable_datetime'])) {
545+
$castValue = $this->serializeDate($castValue);
546+
}
547+
548+
if ($castValue !== null && ($this->isCustomDateTimeCast($castType) ||
549+
$this->isImmutableCustomDateTimeCast($castType))) {
550+
$castValue = $castValue->format(explode(':', $castType, 2)[1]);
551+
}
552+
553+
if ($castValue instanceof DateTimeInterface &&
554+
$this->isClassCastable($key)) {
555+
$castValue = $this->serializeDate($castValue);
556+
}
557+
558+
if ($castValue !== null && $this->isClassSerializable($key)) {
559+
$castValue = $this->serializeClassCastableAttribute($key, $castValue);
560+
}
561+
562+
if ($this->isEnumCastable($key) && (! $castValue instanceof Arrayable)) {
563+
$castValue = $castValue !== null ? $this->getStorableEnumValue($attributes[$key]) : null;
564+
}
565+
566+
if ($castValue instanceof Arrayable) {
567+
$castValue = $castValue->toArray();
568+
}
569+
570+
Arr::set($attributes, $key, $castValue);
571+
}
572+
573+
return $attributes;
574+
}
518575
}

tests/ModelTest.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,8 +577,7 @@ public function testDates(): void
577577
$this->assertInstanceOf(Carbon::class, $user->getAttribute('entry.date'));
578578

579579
$data = $user->toArray();
580-
$this->assertNotInstanceOf(UTCDateTime::class, $data['entry']['date']);
581-
$this->assertEquals((string) $user->getAttribute('entry.date')->format('Y-m-d H:i:s'), $data['entry']['date']);
580+
$this->assertIsString($data['entry']['date']);
582581
}
583582

584583
public function testCarbonDateMockingWorks()

tests/models/Soft.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ class Soft extends Eloquent
1717
protected $connection = 'mongodb';
1818
protected $collection = 'soft';
1919
protected static $unguarded = true;
20-
protected $dates = ['deleted_at'];
20+
protected $casts = ['deleted_at' => 'datetime'];
2121
}

tests/models/User.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ class User extends Eloquent implements AuthenticatableContract, CanResetPassword
3333
use Notifiable;
3434

3535
protected $connection = 'mongodb';
36-
protected $dates = ['birthday', 'entry.date'];
36+
protected $casts = [
37+
'birthday' => 'datetime',
38+
'entry.date' => 'datetime',
39+
];
3740
protected static $unguarded = true;
3841

3942
public function books()

0 commit comments

Comments
 (0)