From f01e7d1423663b864492bb5bedb29ac4f1a84764 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 2 Aug 2019 13:06:02 -0500 Subject: [PATCH 1/2] allow mutated properties to be cast this allows us to return a non-`null` value from our Model mutator in order to continue through the `setAttribute()` method. this maintains backwards compatibility because currently no values are returned from mutators, from which PHP will inherently return `null`. https://www.php.net/manual/en/functions.returning-values.php --- .../Database/Eloquent/Concerns/HasAttributes.php | 6 +++++- tests/Database/DatabaseEloquentModelTest.php | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php index 0eef812e71b2..fc8ee4f08925 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php @@ -568,7 +568,11 @@ public function setAttribute($key, $value) // which simply lets the developers tweak the attribute as it is set on // the model, such as "json_encoding" an listing of data for storage. if ($this->hasSetMutator($key)) { - return $this->setMutatedAttributeValue($key, $value); + $value = $this->setMutatedAttributeValue($key, $value); + + if (is_null($value)) { + return $value; + } } // If an attribute is listed as a "date", we'll convert it from a DateTime diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index 165a3d63ea97..2468cde9bff9 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -68,6 +68,13 @@ public function testAttributeManipulation() $this->assertEquals(json_encode(['name' => 'taylor']), $attributes['list_items']); } + public function testCastAttributeCanBeMutated() + { + $model = new EloquentModelStub; + $model->colors = ['green', ' red', 'blue ', ' orange ', ' p ink ']; + $this->assertEquals(['green', 'red', 'blue', 'orange', 'p ink'], $model->colors->all()); + } + public function testDirtyAttributes() { $model = new EloquentModelStub(['foo' => '1', 'bar' => 2, 'baz' => 3]); @@ -1952,6 +1959,7 @@ class EloquentModelStub extends Model protected $table = 'stub'; protected $guarded = []; protected $morph_to_stub_type = EloquentModelSaveStub::class; + protected $casts = ['colors' => 'collection']; public function getListItemsAttribute($value) { @@ -1973,6 +1981,11 @@ public function setPasswordAttribute($value) $this->attributes['password_hash'] = sha1($value); } + public function setColorsAttribute($value) + { + return array_map('trim', $value); + } + public function publicIncrement($column, $amount = 1, $extra = []) { return $this->increment($column, $amount, $extra); From 2b79208b2643acf58aafd5f9fa539fa5ce2a64b1 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 2 Aug 2019 14:05:19 -0500 Subject: [PATCH 2/2] fix date casting the only way you would make it to this conditional is if the previous `if` was false, so being an `if` or an `elseif` doesn't really make a difference. --- src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php index fc8ee4f08925..203c4f68a76f 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php @@ -578,7 +578,7 @@ public function setAttribute($key, $value) // If an attribute is listed as a "date", we'll convert it from a DateTime // instance into a form proper for storage on the database tables using // the connection grammar's date format. We will auto set the values. - elseif ($value && $this->isDateAttribute($key)) { + if ($value && $this->isDateAttribute($key)) { $value = $this->fromDateTime($value); }