A little trick I've been implementing recently to ensure that data accessed from a Laravel request object has first been validated.

Making sure you validate any input data from the user is crucial for security and ensuring your app stays in a valid state. Validating data is easy peasy lemon squeezy with Laravel’s validation rules in combination with form request objects.

Another thing Laravel does, is make it super easy to access request input data. A form request object extends Laravel’s request object, so accessing a title input is as easy as $request->title, but there lays the potential issue. It can be too easy, let’s take a look at why.

Creating Models from Request Data

In your controller, you’ve probably done something like this to create a pretty simple model:

public function store(PostRequestForm $form)
{
    Post::create([
        'title' => $form->title,
        'content' => $form->content
    ]);
}

or another option might be something like:

public function store(PostRequestForm $form)
{
    Post::create($form->only(['title', 'content']));
}

Both a perfectly valid options and I’ve been doing this myself in my projects. However, recently I was thinking it is very possible to access input from the form that hasn’t been validated. Looking at this, how do I know those are validated inputs?

When I’m in my controller, I don’t know if the form has validated the title or content input…and that scares me - sure, I’m a big kid and should trust that I did validate the data, but with such an important piece of the puzzle I don’t like to take any risks.

Enforcing Valid Data Access

Let’s wrap ourselves up in a security blanket so we can sleep easy. In a form request object we set our rules as per normal:

public function rules()
{
    return [
        'title' => 'required|string|max:255',
        'content' => 'required|string'
    ];
}

and then we add a new method to our request object to keep ourselves in check:

/**
 * @return array
 */
public function validatedInputs()
{
    $keys = array_keys($this->rules());

    return $this->only($keys);
}

Now in our controller we know that our input has been validated by our rules and is of a type that is suitable for our application.

public function store(PostRequestForm $form)
{
    Post::create($form->validatedInputs());
}

😌 that makes me feel better.

Notes

public function rules()
{
    return [
        'users.*.email' => 'required|email'
    ];
}

things start to get a little hairy, but by then you’re probably doing other trickery anyway.


Updates

Looks like we are going to have this baked into the upcoming Laravel release 5.5 thanks to Joseph Silber‏. Very cool - looking forward to trying it!