Laravel Validate Path or Query Parameters in Form Requests
Laravel by default does not provide an easy way to validate path and query parameters. However, many times it is necessary to ensure that a particular ID or entity is valid before the controller method is called. Given a posts/{postId}
route, how would we validate the route parameter (postId
in this case) and any query parameters provided by the client?
Laravel Form Requests provide an easy way to do with with a small adjustment. This Stack Overflow answer and this one show how to validate route parameters. I added in the ability to validate query parameters as shown below.
// The rules to validate the payload and query/route parameters against
public function rules()
{
return [
'post_id' => 'required|exists:posts,id',
'include' => 'sometimes|numeric|nullable',
'name' => 'required|string',
];
}
// Setup the validation of query/route parameters
public function all($keys = null)
{
$data = parent::all();
$data['post_id'] = $this->route('postId');
$data['include'] = $this->query('include');
return $data;
}
However, this can be improved quite easily by creating an abstract request class which all of your other requests can extend to make use of the query and path validation functionality.
By changing the all()
method in the abstract request class, we can easily define what query and path or route parameters that we want to be validated. Consider the following all()
method:
public function all($keys = null)
{
$data = parent::all();
foreach ($this->routeParametersToValidate as $validationDataKey => $routeParameter) {
$data[$validationDataKey] = $this->route($routeParameter);
}
foreach ($this->queryParametersToValidate as $validationDataKey => $queryParameter) {
$data[$validationDataKey] = $this->query($queryParameter);
}
return $data;
}
By overriding the properties in the extending class, we can define the query and route parameters that we'd like to validate. Below is an example of the properties in the request class as well as example rules.
protected $routeParametersToValidate = ['post_id' => 'postId'];
protected $queryParametersToValidate = ['include' => 'include'];
public function rules()
{
return [
'post_id' => 'required|exists:posts,id',
'include' => 'sometimes|numeric|nullable',
'name' => 'required|string',
];
}
You can see the entire codebase here as well as the tests.