diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php index 94e6e95f5288..57f9e8f202a7 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php @@ -433,6 +433,25 @@ protected function getArrayableItems(array $values) return $values; } + /** + * Determine whether an attribute exists on the model. + * + * @param string $key + * @return bool + */ + public function hasAttribute($key) + { + if (! $key) { + return false; + } + + return array_key_exists($key, $this->attributes) || + array_key_exists($key, $this->casts) || + $this->hasGetMutator($key) || + $this->hasAttributeMutator($key) || + $this->isClassCastable($key); + } + /** * Get an attribute from the model. * @@ -448,11 +467,7 @@ public function getAttribute($key) // If the attribute exists in the attribute array or has a "get" mutator we will // get the attribute's value. Otherwise, we will proceed as if the developers // are asking for a relationship's value. This covers both types of values. - if (array_key_exists($key, $this->attributes) || - array_key_exists($key, $this->casts) || - $this->hasGetMutator($key) || - $this->hasAttributeMutator($key) || - $this->isClassCastable($key)) { + if ($this->hasAttribute($key)) { return $this->getAttributeValue($key); } diff --git a/tests/Database/DatabaseEloquentBelongsToManyWithCastedAttributesTest.php b/tests/Database/DatabaseEloquentBelongsToManyWithCastedAttributesTest.php index 34f89e8c49ef..96c3e24b2a48 100644 --- a/tests/Database/DatabaseEloquentBelongsToManyWithCastedAttributesTest.php +++ b/tests/Database/DatabaseEloquentBelongsToManyWithCastedAttributesTest.php @@ -21,6 +21,7 @@ public function testModelsAreProperlyMatchedToParents() { $relation = $this->getRelation(); $model1 = m::mock(Model::class); + $model1->shouldReceive('hasAttribute')->passthru(); $model1->shouldReceive('getAttribute')->with('parent_key')->andReturn(1); $model1->shouldReceive('getAttribute')->with('foo')->passthru(); $model1->shouldReceive('hasGetMutator')->andReturn(false); @@ -29,6 +30,7 @@ public function testModelsAreProperlyMatchedToParents() $model1->shouldReceive('getRelationValue', 'relationLoaded', 'relationResolver', 'setRelation', 'isRelation')->passthru(); $model2 = m::mock(Model::class); + $model2->shouldReceive('hasAttribute')->passthru(); $model2->shouldReceive('getAttribute')->with('parent_key')->andReturn(2); $model2->shouldReceive('getAttribute')->with('foo')->passthru(); $model2->shouldReceive('hasGetMutator')->andReturn(false); diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index 2b8f11eaee8e..7c5e22bd7c3e 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -3024,6 +3024,19 @@ public function testDiscardChanges() $this->assertNull($user->getOriginal('name')); $this->assertNull($user->getAttribute('name')); } + + public function testHasAttribute() + { + $user = new EloquentModelStub([ + 'name' => 'Mateus', + ]); + + $this->assertTrue($user->hasAttribute('name')); + $this->assertTrue($user->hasAttribute('password')); + $this->assertTrue($user->hasAttribute('castedFloat')); + $this->assertFalse($user->hasAttribute('nonexistent')); + $this->assertFalse($user->hasAttribute('belongsToStub')); + } } class EloquentTestObserverStub