Laravel does an incredible job helping developers break their code into smaller parts, which reduces code clutter and makes the code easier to read. I recently discovered how to create a custom form request for handling validation during a form submission.
Before a custom form request
Let’s pretend we have created a Product
model and want to update the name
or price
fields. A ProductController::update()
method will handle the update form submission
Before using a custom form request, the ProductController::update()
method may look like the following.
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Product $product
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Product $product)
{
$this->validate($request, [
'name' => 'required|max:255',
'price' => 'required|numeric',
]);
$product->update(
$request->only('name', 'price')
);
return back()->with('status', 'The product was updated!');
}
This is pretty basic and easy to read. However, the ProductController::update()
method could grow as the application requires more complexity. By moving the validation into it’s own class, we can help reduce code complexity.
Creating the custom request
Using an artisan command, create a custom request.
$ php artisan make:request ProductUpdateRequest
This will create the ProductUpdateRequest.php
file within the app/Http/Requests
directory.
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ProductUpdateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}
The ProductUpdateRequest::authorize()
method will determine if the request can be validated in the first place. This is a good place to check if the user is logged in and if the user has the capability to make the update. For this example, the ProductUpdateRequest::authorize()
method will just return true
.
The ProductUpdateRequest::rules()
method will return the validation rules for the current request.
Copy the validation rules from the ProductController::update()
method to the ProductUpdateRequest::rules()
method.
The custom request class should look like the following.
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ProductUpdateRequest 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|max:255',
'price' => 'required|numeric',
];
}
}
The ProductController::update()
method can now have a ProductUpdateRequest
type-hint for the $request
parameter and the validation inside can be removed.
use App\Http\Requests\ProductUpdateRequest;
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\ProductUpdateRequest $request
* @param \App\Product $product
* @return \Illuminate\Http\Response
*/
public function update(ProductUpdateRequest $request, Product $product)
{
$product->update(
$request->only('name', 'price')
);
return back()->with('status', 'The product was updated!');
}
Since ProductUpdateRequest
inherits from FormRequest
, Laravel will know to inject the class as the $request
parameter as well as run the authorize and validation logic before hand. If the validation fails, Laravel will return the user to the form with the errors.
Check out the Laravel documentation for more information and a guide on creating custom request classes.
Have anything to add that I missed? Let me know.