diff --git a/src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php index e89f65d1cdbb..d663a3835547 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php @@ -27,6 +27,13 @@ trait GuardsAttributes */ protected static $unguarded = false; + /** + * The actual columns that exist on the database and can be guarded. + * + * @var array + */ + protected static $guardableColumns = []; + /** * Get the fillable attributes for the model. * @@ -164,12 +171,30 @@ public function isFillable($key) */ public function isGuarded($key) { - if (strpos($key, '->') !== false) { - $key = Str::before($key, '->'); + if (empty($this->getGuarded())) { + return false; } return $this->getGuarded() == ['*'] || - ! empty(preg_grep('/^'.preg_quote($key).'$/i', $this->getGuarded())); + ! empty(preg_grep('/^'.preg_quote($key).'$/i', $this->getGuarded())) || + ! $this->isGuardableColumn($key); + } + + /** + * Determine if the given column is a valid, guardable column. + * + * @param string $key + * @return bool + */ + protected function isGuardableColumn($key) + { + if (! isset(static::$guardableColumns[get_class($this)])) { + static::$guardableColumns[get_class($this)] = $this->getConnection() + ->getSchemaBuilder() + ->getColumnListing($this->getTable()); + } + + return in_array($key, static::$guardableColumns[get_class($this)]); } /** diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index f0e56677fd64..acb9598ea8c8 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -10,6 +10,7 @@ use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Database\Connection; use Illuminate\Database\ConnectionResolverInterface; +use Illuminate\Database\ConnectionResolverInterface as Resolver; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\JsonEncodingException; @@ -1014,11 +1015,21 @@ public function testUnderscorePropertiesAreNotFilled() public function testGuarded() { $model = new EloquentModelStub; + + EloquentModelStub::setConnectionResolver($resolver = m::mock(Resolver::class)); + $resolver->shouldReceive('connection')->andReturn($connection = m::mock(stdClass::class)); + $connection->shouldReceive('getSchemaBuilder->getColumnListing')->andReturn(['name', 'age', 'foo']); + $model->guard(['name', 'age']); $model->fill(['name' => 'foo', 'age' => 'bar', 'foo' => 'bar']); $this->assertFalse(isset($model->name)); $this->assertFalse(isset($model->age)); $this->assertSame('bar', $model->foo); + + $model = new EloquentModelStub; + $model->guard(['name', 'age']); + $model->fill(['Foo' => 'bar']); + $this->assertFalse(isset($model->Foo)); } public function testFillableOverridesGuarded() @@ -2134,7 +2145,7 @@ public function getDates() class EloquentModelSaveStub extends Model { protected $table = 'save_stub'; - protected $guarded = ['id']; + protected $guarded = []; public function save(array $options = []) {