This was already reported in https://github.com/laravel/framework/issues/34073 , https://github.com/laravel/framework/issues/35297 , and probably others, but these issues were closed without due consideration.
The problem is that the nature of the security patch as described in the published announcements is not consistent with the observed behavior, so please read this carefully and don't close it without considering the test that I've included.
From https://blog.laravel.com/security-release-laravel-61834-7232 (emphasis mine):
Any attributes containing table names that are not explicitly declared as fillable will be discarded.
Table names, not column names.
This security release will be a breaking change for applications that were relying on the undocumented table name stripping during mass assignment.
My application does not rely on the table name stripping during mass assignment. It relies only on the ability to specify individual columns in the protected $guarded property, which was broken in 7.24.0.
From https://blog.laravel.com/security-release-laravel-61835-7240 (emphasis mine):
Today's patch fixes this and other potential unexpected behaviors by comparing the column that is being updated with an actual list of database columns that exist on the database table. We retrieve this column list using Laravel's schema inspection facilities that already existed in the framework. Note that this will introduce one extra database query to retrieve the column listing when attempting to mass assign attributes to a model that is using the $guarded property.
This explanation makes it perfectly clear that the breakage was not intentional. To the contrary, it states explicitly that specifying individual columns in the protected $guarded property's array is precisely what will trigger the additional checks that were added in this patch.
However, observed behavior is now that when any column is specified as guarded, _no_ column is fillable. Again, the observed breakage is inconsistent with the patch's stated purpose, and contradicts it explicitly in two respects.
To elaborate further, in laravel/framework versions < 7.24.0, it was possible to specify individual columns in a model's protected $guarded property, e.g.:
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class UserGuarded extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $guarded = ['id'];
}
But https://github.com/laravel/framework/commit/897d107775737a958dbd0b2f3ea37877c7526371 appears to have broken that capability.
User model per snippet above, i.e., replace protected $fillable = ['name', 'email', 'password']; by protected $guarded = ['id'];.laravel/framework 7.23.0 but fails in 7.24.0:<?php
namespace Tests\Unit;
use App\User;
use PHPUnit\Framework\TestCase;
class MassAssignmentTest extends TestCase
{
/**
* @test
*/
public function massAssignmentWorksWhenGuardedSpecified()
{
$model = new User(['email' => '[email protected]']);
$this->assertEquals('[email protected]', $model->email);
}
}
This is definitely a breaking change for a much larger audience than appears to have been intended.
Laravel 7 is no longer receiving any code changes. However, your test passes in Laravel 8 so if you need this behavior I suggest upgrading to that version - it is not a difficult upgrade:


Thank you for taking a look so quickly; I appreciate it.
The test fails for me in Laravel 8, too. (I did in fact test it on Laravel 8 before I bothered posting, but I realize now that I forgot to update the Laravel version I provided; my apologies!)
What are you using for the protected $guarded property in the User model class when you test this?
The test only passes if I use protected $guarded = [], but not if I use protected $guarded = ['id']. That is the crux of the issue here.
I just setup the whole test again... works fine:

@cbj4074 I also tested with Laravel 8 and it indeed works.
But, there was a change in Laravel 8 on how unit tests are processed. Maybe that could be what is causing the issue when testing with Laravel 8.
First I just modified the User model and copied the test code to a unit test and got a failing test with a message related to the database connection.
Then I remembered Unit Tests no longer extends from Laravel's TestCase class by default, therefore some parts of the framework are not initialized/available for those tests.
Afterwards I tried with a Feature Test, where the framework is fully available and it worked.
Hope it helps.
@rodrigopedra That is exactly the case! Thank you for clarifying that!
Indeed, the test was failing with Error : Call to a member function connection() on null, and that's exactly why.
@taylorotwell Thanks again for double-checking my work and proving that this does in fact work correctly in Laravel 8.
Most helpful comment
@rodrigopedra That is exactly the case! Thank you for clarifying that!
Indeed, the test was failing with
Error : Call to a member function connection() on null, and that's exactly why.@taylorotwell Thanks again for double-checking my work and proving that this does in fact work correctly in Laravel 8.