Skip to content

Commit d41f408

Browse files
authored
[12.x] fix: Models having inconsistent guarding behaviour (#56381)
* bug: adding unittest for guarded models Adding a unit test to cover edge cases where models exhibit inconsistent behaviour when the $guard property is empty but the $fillable is not. A MassAssignmentException is thrown. this happens because getGuarded in GuardsAttributes has two different mechanisms for unguarding a model. 1. $unguarded boolean property (default: false) 2. $guarded array property (default: ['*']) `getGuarded()` uses the $guarded and checks if it's false to return and empty array. `fillableFromArray()` uses $unguarded and $fillable properties to test if the model is unguarded. Both methods should use $unguarded for consistent behaviour. * bug: changing getGuarded to use $unguarded * feat: updatinng docblock
1 parent a72bd3b commit d41f408

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ trait GuardsAttributes
1414
/**
1515
* The attributes that aren't mass assignable.
1616
*
17-
* @var array<string>|bool
17+
* @var array<string>
1818
*/
1919
protected $guarded = ['*'];
2020

@@ -28,7 +28,7 @@ trait GuardsAttributes
2828
/**
2929
* The actual columns that exist on the database and can be guarded.
3030
*
31-
* @var array<string>
31+
* @var array<class-string,list<string>>
3232
*/
3333
protected static $guardableColumns = [];
3434

@@ -75,7 +75,7 @@ public function mergeFillable(array $fillable)
7575
*/
7676
public function getGuarded()
7777
{
78-
return $this->guarded === false
78+
return self::$unguarded === true
7979
? []
8080
: $this->guarded;
8181
}

tests/Database/DatabaseEloquentModelTest.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use Illuminate\Contracts\Database\Eloquent\Castable;
1111
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
1212
use Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes;
13-
use Illuminate\Contracts\Encryption\Encrypter;
1413
use Illuminate\Contracts\Events\Dispatcher;
1514
use Illuminate\Database\Connection;
1615
use Illuminate\Database\ConnectionResolverInterface;
@@ -47,7 +46,6 @@
4746
use Illuminate\Database\Query\Processors\Processor;
4847
use Illuminate\Support\Carbon;
4948
use Illuminate\Support\Collection as BaseCollection;
50-
use Illuminate\Support\Facades\Crypt;
5149
use Illuminate\Support\Fluent;
5250
use Illuminate\Support\HtmlString;
5351
use Illuminate\Support\InteractsWithTime;
@@ -1704,6 +1702,27 @@ public function testGuarded()
17041702
Model::preventSilentlyDiscardingAttributes(false);
17051703
}
17061704

1705+
public function testGuardedWithFillableConfig(): void
1706+
{
1707+
$model = new EloquentModelStub;
1708+
$model::unguard();
1709+
1710+
EloquentModelStub::setConnectionResolver($resolver = m::mock(Resolver::class));
1711+
$resolver->shouldReceive('connection')->andReturn($connection = m::mock(stdClass::class));
1712+
$connection->shouldReceive('getSchemaBuilder->getColumnListing')->andReturn(['name', 'age', 'foo']);
1713+
1714+
$model->guard([]);
1715+
$model->fillable(['name']);
1716+
$model->fill(['name' => 'Leto Atreides', 'age' => 51]);
1717+
1718+
self::assertSame(
1719+
['name' => 'Leto Atreides', 'age' => 51],
1720+
$model->getAttributes(),
1721+
);
1722+
1723+
$model::reguard();
1724+
}
1725+
17071726
public function testUsesOverriddenHandlerWhenDiscardingAttributes()
17081727
{
17091728
EloquentModelStub::setConnectionResolver($resolver = m::mock(Resolver::class));

0 commit comments

Comments
 (0)