Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

pmusa's avatar
Level 2

Why Mass Assignments?

Hello, I'm new to Laravel. I learned how to solve the issue with the MassAssignmentException, however I do not understand why such a concept was introduced. Here is for example what's inside my Posts controller :

    Post::create([
        'title' => request('title'),
        'body' => request('body')
    ]);

As you can see, I clearly say I want to INSERT the title and the body. Why, ON TOP OF THAT, do I need to define what's fillable or guarded? Why such a redundancy?

Also, are the "created_at" and "updated_at" columns of my DB immune by default, or can a hacker forge a POST request to alter both those columns as well?

Thank you for your time.

0 likes
22 replies
pmusa's avatar
Level 2

I understand that. What I do not understand is: I clearly state on the piece of code above that I just want to store the title and the body, why would Laravel even consider any other var the user might submit? Let's say a hacker also submits a "user_id" (which stores posts author id), well who cares?

Cronix's avatar
Cronix
Best Answer
Level 67

For one thing, a lot of people like to just use Post::create($request->all()) for simplicity instead of naming out each individual parameter, which introduces security concerns. What if I added is_admin=1 to the post request and there happened to be an is_admin field? It would just set it.

There is also the $guarded parameter to play with, which is a blacklist instead of the $fillable whitelist. you can just do $guarded = [] and not worry about having to set fields in $fillable every time. If you're explicitly naming what you're saving each time (like your example), that's what I'd do. Laravel is just flexible and allows you to work in different ways depending on how you want to do things.

1 like
jlrdw's avatar

why would Laravel even consider any other var the user might submit?

It wouldn't in that case, mass assignment, mass being the key word is when a whole array is sent instead of getting the post data one at a time.

It's just for added security.

Bottom line, no array all at once usually means no problem.

In fact go to https://laravel.com/docs/5.8/eloquent

And in the index click mass assignment, Taylor gives a good explanation.

pmusa's avatar
Level 2

I'm afraid I still do not understand. Within the Eloquent's method called "create()", I pass an array as a parameter (see the 4 lines code above). That array just contains the "title" and the "body", which means I just want to save/INSERT the "title" and the "body". Now let's say a hacker also submits a $_POST['is_admin']=1 Let's also say I indeed have a "is_admin" column within my "posts" table. I do NOT care if the user sends me a forged "is_admin", since the code above states that I just want to save the "title" and the "body", nothing else! I've never seen anyone do such a thing as "Post::create($request->all())". Don't they even validate/controle every single user inputs? "If you're explicitly naming what you're saving each time (like your example)" --> That is indeed what I have always been doing.

pmusa's avatar
Level 2

Post::create([ 'title' => request('title'), 'body' => request('body') ]);

those 4 lines translate into: "fill the title and the body in the database". why do I need to tell Laravel "hey, btw, title and body are fillable" on top of that in the Model file? I do not understand that redundancy. why such a behavior? also, by default?

jlrdw's avatar

I have explained cronix has explained and Taylor explains in the documentation.

I don't know how else to get the point across.

It's for if you send an entire array.

okay you don't so no problem but some people do.

Taylor put it as a safeguard you're making too much out of really nothing.

pmusa's avatar
Level 2

What if I create a custom parent model "Model" (that extends the Eloquent model). Then I state within "Model" that $guarded is an empty array. Then Post model extends my custom model. Then I keep my Post controller as it currently is: Post::create([ 'title' => request('title'), 'body' => request('body') ]);

Will it save "is_admin=1" if a user sends such a thing?

jlrdw's avatar

The very first thing you should do if you already know PHP is to take

https://laracasts.com/series/laravel-from-scratch-2018

It's free.

If you are new also to PHP there's a free introductory series on that as well.

And just set up the models the way Taylor recommends the man knows what he's doing.

I have been doing this stuff since the late 1980s and have learned a lot from Taylor and Jeffrey.

Yes You to @cronix

MichaelAndish's avatar

If you want to create a post and you have MassAssignment Error you should be pass required column to your model.

But if you worry about a hacker and accessible another user you should read more about Middleware and Request Lifecycle in Laravel.

you can manage your user with middleware and permission in your routes. you can read more about user management and role permission in these 2 packages:

https://github.com/spatie/laravel-permission https://github.com/santigarcor/laratrust

pmusa's avatar
Level 2

"And just set up the models the way Taylor recommends the man knows what he's doing." No. I like to understand what I do and why it's done that way. I found the answer in the (great) videos though. Thank you. I now understand that it's all related to the fact that some devs just send the entire array with request->all(), without explicitly naming each key. I didn't even think someone would do that. That's crazy. I'm actually glad he does not allow that by default. It makes sens to me now. Thank you all for your answers and your patience.

jlrdw's avatar

I now understand that it's all related to the fact that some devs just send the entire array with request->all()

Good gracious that was answered right away and explained in that stackoverflow article.

Cronix explained it And Taylor states that in the documentation.

So you're saying it took all that and a video to get a simple point across.

pmusa's avatar
Level 2

That's right. The fact that someone would use "request->all()" just blew my mind.

jlrdw's avatar

I don't like request all neither I do one at a time.

Cronix's avatar

It's like, pick your poison. Either use a fat controller (naming out all fields to save) or use a fat model (explicitly name all fields model can save in $fillable). They both do the exact same thing. Some prefer that logic out of the controller to have very thin controllers. It all comes down to your particular (or teams) coding style.

For instance, if I have a form with 30 fields, I don't want all of that logic in various methods in the controller (for storing, updating, etc). Having a single whitelist array in the model leaves the controller a lot thinner, and less code overall (just one whitelist in model for creating/updating vs naming out the fields in both the store/update methods - that's 2x the code). If you add/alter fields, you also have multiple places to update it vs just updating a single $fillable array.

1 like
Cronix's avatar

Sure, usually outside the controller using a Form Request class, which is typehinted in the method signature. https://laravel.com/docs/5.8/validation#form-request-validation

The validation happens before it hits the controller so you don't need all of that logic in a big fat controller. I try to adhere to DRY and Single Responsibility Principle/Separation of Concerns where it makes sense.

jlrdw's avatar

A note on validation also:

If php strip_tags is used on all request that have text, then simple validation can be achieved using JS.

So the basic rule:

  • Not using strip_tags = have good back end validation
  • Using strip_tags = either way.

Validation has a lot to do with a user who cannot seem to enter data properly, i.e., a field needs to be a least 6 characters, but they entered 4.

To me strip_tags is the most important. But you still need at least basic validation to at least attempt to get proper data entered.

To note date fields and numeric do not require strip_tags, you cannot use HTML code in these data types.

Snapey's avatar

Any client side validation is for the benefit and convenience of the user.

server side validation is for the integrity of the data. Client side validation is no substitute.

simple.

2 likes
jlrdw's avatar

server side validation is for the integrity

Server side validation never stops someone from entering

Xyz

Instead of

Bob

But yes it can ensure the correct type of data is entered.

But validation has nothing to do with

htmlspecialchars or strip_tags

And former still allowing the tags to sit there just coded a certain way.

I'd rather remove the tags all together.

Not counting something like this a forum.

But hopefully the folks at a company will enter Bob instead of XYZ.

I know the rule never trust user input, but no amount of programming will ever catch every possible mistake.

Heck while back my Pharmacy entered 2018 on a date I got a prescription and it was really 2019 so refill time it was expired.

But you have to remember we are all human and we all make mistakes, to include data entry.

I agree validation helps cut down on data entry mistakes but will never catch everything.

In other words I am not disagreeing with anybody.

simple

I understood Crystal clear.

Please or to participate in this conversation.