Laravel provides several different approaches to validate your application’s incoming data. It is most common to use the validate method available on all incoming HTTP requests. However, in this topic, we will use Form Requests in different ways.
First of all, I don’t think using a small validation in the controller will harm your code readability but on the other hand, if you are willing to handle more complex validation scenarios, you may wish to create a “Form Request“.
Form requests are custom request classes that encapsulate their own validation and authorization logic.
Let’s create our own form request class, all you need is to run this command:
php artisan make:request StoreUserRequest
A new StoreUserRequest
class will be generated under "\App\Http\Requests" namespace containing a rules() & authorize() methods.
Let’s add some quick validation under rules() method
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required|min:3|max:50',
'email' => 'required|email|unique:users',
'password' => 'required|confirmed|min:8',
//... more validation
];
}
After that, we will inject our new Form request in the controller store() method
/**
* Store a new user.
*
* @param \App\Http\Requests\StoreUserRequest $request
* @return Illuminate\Http\Response
*/
public function store(StoreUserRequest $request)
{
// The incoming request is valid...
// Retrieve the validated input data...
$validatedData = $request->validated();
}
So far so good, if the validation is valid we will get our validated data from Form request otherwise a Validation Exception will be thrown.
Now, what about the update, clearly we need to use another form request UpdateUserRequest
with its rules and inject it in the controller update() method.
So this is the first and the simple approach used so far.
The second approach is using one class to handle the store and update rules, so, we will run the command again and create new Form Request by naming it UserRequest
.
We create store() and update() functions and call them in rules() function by using isMethod() we're checking the HTTP request method if is it a POST or other than that, you may be specific and check if it is a PUT/PATCH.
As you may notice we can also share validations used in both methods and concatenate it with the proper validation function.
public function rules()
{
return ['name' => 'required|min:3|max:50']
+
($this->isMethod('POST') ? $this->store() : $this->update());
}
protected function store()
{
return [
'email' => 'required|email|unique:users',
'password' => 'required|confirmed|min:8',
//… more validation
];
}
protected function update()
{
return [
'email' => 'required|email|unique:users,email,'.$this->user()->id,
'logo' => 'nullable|image|max:1024',
'bio' => 'nullable|max:300',
'github_url' => 'nullable|url'
//… more validation
];
}
After that, we will inject UserRequest
in both store() and update() methods.
Now, we have one class that serve different validation depends on HTTP request.
/**
* Store a new user.
*/
public function store(UserRequest $request)
{
$validated = $request->validated();
}
/**
* Update user.
*/
public function update(UserRequest $request)
{
$validated = $request->validated();
}
I will name the third approach “ResourceFormRequest” and it will be a little bit different from the others.
First I’ll create a BaseFormRequest
that contains all resourceful methods, feel free to use your own naming just be careful when you name your methods to not end up overriding Request class methods.
After that, create UserRequest
and extends BaseFormRequest
, and override existing methods with your rules, finally inject the UserRequest inside your controller methods.
Our Resource Form Request can handle now a Controller resource and you end up with one file that manage all validations of specific Model instead of separate files which personally I don't like it.
I think there's a lot of approaches that we can follow and feel free to share your best approach or other approaches you have.
Finally, if you are reading this line I think the topic was interesting for you.
Thank you
Top comments (12)
Not bad, but i guess it's a little bit over-engineered
I prefer to create another form request class for the update method.
+1 to this. I've created two classes both extending the FormRequest class for this. Alternatively you could create a super class in between for inheritance. While the proposed method in this article isn't bad, I prefer this method personally
It just depend on how you want to structure your project.
This!...
what about authorize()? for the store(), update(), destroy(), view() ?
Thank you Othmane, this is really good writeup for me to understand, maybe just some little typos in 1st & 3rd pictures, I think
It's my pleasure that was helpful for you.. and thank you for pointing the typos :)
(y)
ok, thats good. i want to call
$controller->store()
manually. how can i create request forstore
method ???Why this does not work inside form request?
$this->input('notification_type_id', null) // Always returns null
Thanks to share this idea. It's different approach to learn.
Such a great article, but I was wondering how to pass data like route parameters into the form request, I tried many techniques as per Laravel docs but unluckily did not work for the form request.