Skip to content

Commit 87741d7

Browse files
authored
PHPORM-148 Fix null in datetime fields and reset time in date field with custom format (#2741)
- Fix #2729 by removing the method `Model::castAttribute()` that was introduced by #2658 in 4.1.0. Tests added to ensure `null` is allowed in `date`, `datetime`, `immutable_date`, `immutable_datetime` and the variants with custom formats. - Change the behavior of `immutable_date:j.n.Y H:i` (with custom format), to reset the time. This behave differently than [Laravel 10.46 that treats it like a `immutable_datetime`](https://github.com/laravel/framework/blob/v10.46.0/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L866-L869).
1 parent 7af9a1a commit 87741d7

File tree

4 files changed

+54
-17
lines changed

4 files changed

+54
-17
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# Changelog
22
All notable changes to this project will be documented in this file.
33

4-
## [4.1.3] - unreleased
4+
## [4.1.3] - 2024-03-05
55

6-
* Fix the timezone of `datetime` fields when they are read from the database by @GromNaN in [#2739](https://github.com/mongodb/laravel-mongodb/pull/2739)
6+
* Fix the timezone of `datetime` fields when they are read from the database. By @GromNaN in [#2739](https://github.com/mongodb/laravel-mongodb/pull/2739)
7+
* Fix support for null values in `datetime` and reset `date` fields with custom format to the start of the day. By @GromNaN in [#2741](https://github.com/mongodb/laravel-mongodb/pull/2741)
78

89
## [4.1.2] - 2024-02-22
910

src/Eloquent/Model.php

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,10 @@ protected function transformModelValue($key, $value)
205205
if ($this->hasCast($key) && $value instanceof CarbonInterface) {
206206
$value->settings(array_merge($value->getSettings(), ['toStringFormat' => $this->getDateFormat()]));
207207

208+
// "date" cast resets the time to 00:00:00.
208209
$castType = $this->getCasts()[$key];
209-
if ($this->isCustomDateTimeCast($castType) && str_starts_with($castType, 'date:')) {
210-
$value->startOfDay();
210+
if (str_starts_with($castType, 'date:') || str_starts_with($castType, 'immutable_date:')) {
211+
$value = $value->startOfDay();
211212
}
212213
}
213214

@@ -315,19 +316,6 @@ protected function fromDecimal($value, $decimals)
315316
return new Decimal128($this->asDecimal($value, $decimals));
316317
}
317318

318-
/** @inheritdoc */
319-
protected function castAttribute($key, $value)
320-
{
321-
$castType = $this->getCastType($key);
322-
323-
return match ($castType) {
324-
'immutable_custom_datetime','immutable_datetime' => str_starts_with($this->getCasts()[$key], 'immutable_date:') ?
325-
$this->asDate($value)->toImmutable() :
326-
$this->asDateTime($value)->toImmutable(),
327-
default => parent::castAttribute($key, $value)
328-
};
329-
}
330-
331319
/** @inheritdoc */
332320
public function attributesToArray()
333321
{

tests/Casts/DateTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ public function testDate(): void
5252
self::assertInstanceOf(Carbon::class, $refetchedModel->dateField);
5353
self::assertInstanceOf(UTCDateTime::class, $model->getRawOriginal('dateField'));
5454
self::assertEquals(now()->subDay()->startOfDay()->format('Y-m-d H:i:s'), (string) $refetchedModel->dateField);
55+
56+
$model = Casting::query()->create();
57+
$this->assertNull($model->dateField);
58+
59+
$model->update(['dateField' => null]);
60+
$this->assertNull($model->dateField);
5561
}
5662

5763
public function testDateAsString(): void
@@ -84,6 +90,12 @@ public function testDateWithCustomFormat(): void
8490

8591
self::assertInstanceOf(Carbon::class, $model->dateWithFormatField);
8692
self::assertEquals(now()->startOfDay()->subDay()->format('j.n.Y H:i'), (string) $model->dateWithFormatField);
93+
94+
$model = Casting::query()->create();
95+
$this->assertNull($model->dateWithFormatField);
96+
97+
$model->update(['dateWithFormatField' => null]);
98+
$this->assertNull($model->dateWithFormatField);
8799
}
88100

89101
public function testImmutableDate(): void
@@ -105,6 +117,12 @@ public function testImmutableDate(): void
105117
Carbon::createFromTimestamp(1698577443)->subDay()->startOfDay()->format('Y-m-d H:i:s'),
106118
(string) $model->immutableDateField,
107119
);
120+
121+
$model = Casting::query()->create();
122+
$this->assertNull($model->immutableDateField);
123+
124+
$model->update(['immutableDateField' => null]);
125+
$this->assertNull($model->immutableDateField);
108126
}
109127

110128
public function testImmutableDateWithCustomFormat(): void
@@ -126,5 +144,11 @@ public function testImmutableDateWithCustomFormat(): void
126144
Carbon::createFromTimestamp(1698577443)->subDay()->startOfDay()->format('j.n.Y H:i'),
127145
(string) $model->immutableDateWithFormatField,
128146
);
147+
148+
$model = Casting::query()->create();
149+
$this->assertNull($model->immutableDateWithFormatField);
150+
151+
$model->update(['immutableDateWithFormatField' => null]);
152+
$this->assertNull($model->immutableDateWithFormatField);
129153
}
130154
}

tests/Casts/DatetimeTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ public function testDatetime(): void
3636
self::assertInstanceOf(Carbon::class, $model->datetimeField);
3737
self::assertInstanceOf(UTCDateTime::class, $model->getRawOriginal('datetimeField'));
3838
self::assertEquals(now()->subDay()->format('Y-m-d H:i:s'), (string) $model->datetimeField);
39+
40+
$model = Casting::query()->create();
41+
$this->assertNull($model->datetimeField);
42+
43+
$model->update(['datetimeField' => null]);
44+
$this->assertNull($model->datetimeField);
3945
}
4046

4147
public function testDatetimeAsString(): void
@@ -70,6 +76,12 @@ public function testDatetimeWithCustomFormat(): void
7076

7177
self::assertInstanceOf(Carbon::class, $model->datetimeWithFormatField);
7278
self::assertEquals(now()->subDay()->format('j.n.Y H:i'), (string) $model->datetimeWithFormatField);
79+
80+
$model = Casting::query()->create();
81+
$this->assertNull($model->datetimeWithFormatField);
82+
83+
$model->update(['datetimeWithFormatField' => null]);
84+
$this->assertNull($model->datetimeWithFormatField);
7385
}
7486

7587
public function testImmutableDatetime(): void
@@ -92,6 +104,12 @@ public function testImmutableDatetime(): void
92104
Carbon::createFromTimestamp(1698577443)->subDay()->format('Y-m-d H:i:s'),
93105
(string) $model->immutableDatetimeField,
94106
);
107+
108+
$model = Casting::query()->create();
109+
$this->assertNull($model->immutableDatetimeField);
110+
111+
$model->update(['immutableDatetimeField' => null]);
112+
$this->assertNull($model->immutableDatetimeField);
95113
}
96114

97115
public function testImmutableDatetimeWithCustomFormat(): void
@@ -113,5 +131,11 @@ public function testImmutableDatetimeWithCustomFormat(): void
113131
Carbon::createFromTimestamp(1698577443)->subDay()->format('j.n.Y H:i'),
114132
(string) $model->immutableDatetimeWithFormatField,
115133
);
134+
135+
$model = Casting::query()->create();
136+
$this->assertNull($model->immutableDatetimeWithFormatField);
137+
138+
$model->update(['immutableDatetimeWithFormatField' => null]);
139+
$this->assertNull($model->immutableDatetimeWithFormatField);
116140
}
117141
}

0 commit comments

Comments
 (0)