A while ago when Laravel 5.5 wasn’t released yet Jeffrey Way started a “What’s New in Laravel 5.5” serie on Laracasts. In the second lesson Streamlined Request Validation Jeffrey introduced us to the validated data array when validating a request:
public function store() { $validatedData = request()->validate([ 'title' => 'required', 'body' => 'required', ]); }
Normally you would do something like request()->all()
which isn’t always save if you’re not setup the mass assignment variables on the model right. For example when you’ve disabled mass assignment by adding protected $guarded = [];
to a model. A better way is to use request()->only()
with the fields you need. With the above example that would be: request()->only(['title', 'body'])
but that’s feels like duplication right? You’ve already defined the fields in the validation array. From Laravel 5.5 $validatedData
will output an array with the validated fields, the same as request()->only()
would do.
What about Form Requests?
The first thing I was thinking when I’ve watched that lesson; is there something similar when using Form Requests? I’m not a big fan of validating data in my controller. A comment under the lesson brought me here: laravel-validator which introduced that functionality to Laravel 5.4 with:
public function store(FormRequest $request) { Page::create($request->valid()); }
But Laravel 5.5 introduced the validated()
method (currently still undocumented) so that package isn’t needed anymore and confirmed by the author. I did find a bug with it but was fixed already in Laravel 5.5.4.
What if not all the data should be saved to the model?
In a project I’m currently working on I’m using Spatie’s Medialibrary package so I’ve rules to validate images and lately I’m using protected $guarded = [];
on all my models to disable the mass assignment checks. Let’s say we’ve a page with a title
, body
and image
. In our rules()
method on our PageRequest
we’ve these rules:
return [ 'title' => 'required', 'body' => 'required', 'image' => 'image' ];
When we save the page with Page::create($request->validated());
we’ll get a database error because there is no image
column. Spatie’s Medialibrary saves all the media in a seperated table so we don’t have a image
column on our pages
table. After we’ve saved the page we’ll process the image.
We’ve a few option to fix this:
- Instead of using
protected $guarded = [];
we could specify the fillable ones withprotected $fillable = ['title', 'body'];
. - We could use
Page::create($request->only('title', 'body'));
here instead of thevalidated()
function. - We exclude the image:
Page::create(collect($request->validated())->except(['image'])->toArray());
I’m using option 3, it may look like the longest / most complex option but if you’re getting more and more fields you’ll see it’s the easiest because it’s just a blacklist of fields you don’t want. You could refactor this back to your model so the blacklist is defined there.
What option do you prefer?