Data validation is one of the most important part of applications. Usually we don’t want to allow users to send garbage data, so we want to make sure that everything we save (usually in database) is as expected. We trim strings, we make sure url is really url and not user name, we make sure number is really a number. In Laravel it’s really easy to add validation to your application but when it comes to more complex things for many developers, especially beginners have difficulty to add validation layer.
In Laravel there are 2 basic ways of validation, in fact I use only one of them because it’s much more flexible and allow to put additional logic.
Validation in controller
The easiest way of validation is using it directly in controller. In fact we have here 2 very similar ways. Let’s assume we want to validate that user name and surname are valid. We can write code like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class UserController extends Controller { public function store(Request $request) { $this->validate($request, [ 'name' => 'required|string|min:3|max:100', 'surname' => 'required|string|min:5|max:100', ]); // here we know name and surname are valid so we can add user } } |
or alternatively like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class UserController extends Controller { public function store(Request $request) { $request->validate([ 'name' => 'required|string|min:3|max:100', 'surname' => 'required|string|min:5|max:100', ]); // here we know name and surname are valid so we can add user } } |
Both ways do exactly the same but well, they are not very flexible. Yes, that’s pretty easy and quick do add such validation, but when you need to extend it or make it more complex probably you will eventually use second method.
Validation using Form requests
Second method of validation in Laravel is using Form requests. This is preferred way for me and I use it in all cases, also very simple because it’s quite flexible and allow to make any complex changes in future. Let’s rewrite our initial controller and add Form request validation.
Our controller method now looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php namespace App\Http\Controllers; use App\Http\Requests\UserRequest; class UserController extends Controller { public function store(UserRequest $request) { // here we know name and surname are valid so we can add user } } |
and our form request class like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class UserRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'name' => 'required|string|min:3|max:100', 'surname' => 'required|string|min:5|max:100', ]; } } |
First of all, our controller is much cleaner now. We don’t have anything related to validation in our controller so we can focus on code logic in controller. But in our request class, first notice authorize method. This method tells whether user is authorized or not to run this request. In fact I always set it to true, but in very easy applications you can put authorization layer here. In fact in my real app I always have one base Request class and all my form requests classes extend from this one.
But the most important here is in fact our rules method. In this method we put validation rules. Looking first at this there is no visible benefit. Rules are looking exactly the same as we put them in controller but we had to do much more – create separate class, implement method and so on. Yes, in this very simple scenario that’s true but as I said I use this way always – no matter of complexity.
As you see, current example was very simple, but usually validation is much complex. Also sometimes you might want to add custom rules or use object rules like for example Rule::unique (there’s also string version but very hard to remember). That’s why I never use pipe symbol for validation rules. I prefer to use array syntax for validation rules. In real life scenario, I would definitely had this method looking like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public function rules() { return [ 'name' => [ 'required', 'string', 'min:3', 'max:100', ], 'surname' => [ 'required', 'string', 'min:5', 'max:100', ], ]; } |
Let’s go a bit further. In real application you might have really different validation rules based on input criteria. For example for our case let’s assume that when name has at least 7 characters, than surname can have at least 2 characters and otherwise it should be at least 5 characters (the same as it was before). Using Form requests and array syntax, it’s quite simple:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public function rules() { $rules = [ 'name' => [ 'required', 'string', 'min:3', 'max:100', ], 'surname' => [ 'required', 'string', 'max:100', ], ]; if (mb_strlen($this->input('name')) >= 7) { $rules['surname'][] = 'min:2'; } else { $rules['surname'][] = 'min:5'; } return $rules; } |
The same way we can add some other rules or even custom validation rules. As you see syntax array with plain PHP is just enough. And you can imagine it would be a bit too long to put this just in controller validation.
There are also some more complex scenarios that I will describe in following posts, but whenever you have doubt – what validation way you should choose in your application – I recommend to use Form requests.
Laravel validation - use multiple Form requests for complex scenarios - Laravel developers tips
[…] a long time ago I’ve already written about different ways of data validation in Laravel applications. Today I would like to show how you could use multiple Form requests classes when you […]