-
Notifications
You must be signed in to change notification settings - Fork 107
Description
I've searched for previous issues and into the minor releases we have not upgraded to yet (we're on 1.0.0) and this specifically did not seem to have been addressed.
As it stands the same query rules will be applied to index and read requests on a resource. I think this is a fairly ok generalisation, however in some cases it may be preferential to to be able to specify slightly different rules for each, and this is not possible without an override currently.
In our case, we've created an endpoint meant exclusively for searching through a large database. We want to limit how many results can be returned so we've specified a mandatory query filter param for the index which allows searching on various columns. We also want to allow read access to specific resources, but these would not need the same mandatory query parameter.
Our queryRules() function looks like this;
/**
* Get query parameter validation rules.
*
* @return array
*/
protected function queryRules(): array
{
return [
// As this is the search API, a query is required
// - Numeric values may be 1 or more character, will be interpreted as an id
// - Anything else this must be more than 3 characters, without whitespace
'filter.query' => [
'required',
function ($attribute, $value, $fail) {
if (!is_integer($value) && strlen(preg_replace("/[\s]+/", '', $value)) < 3) {
return $fail("The $attribute can only be less than 3 as an integer.");
}
},
],
// We want to limit the number or results available
// By requiring a size parameter and limiting the
// page number size only one page can be retrieved
'page.number' => 'filled|numeric|max:1',
'page.size' => 'required|filled|numeric|between:1,100',
];
}
This works fine for index requests and limits results quite effectively. But if you then try to request a specific resource it will use the same rules and return the following error;
{
"errors": [
{
"status": "400",
"title": "Invalid Query Parameter",
"detail": "The filter.query field is required.",
"source": {
"parameter": "filter.query"
}
}
]
}
Which is not desirable in our case.
This was easy to solve by overriding the fetchQuery() function and adding 'filter.query' to the exclude list;
public function fetchQuery(array $params): ValidatorInterface
{
return $this->validatorForQuery(
$params,
$this->queryRulesExcludingFilterId('sort', 'page', 'filter.query'),
$this->queryMessages(),
$this->queryAttributes()
);
}
For the 1.x version this use-case could probably be resolved by allowing implementations to add to a query parameter exclude list of some sort for read requests in the validator, but this might leave out other use-cases.
It seems like the logic to retrieve the right parameters to allow or exclude from index or read requests differs quite a bit, so for 2.x I would probably suggest allowing for different rulesets altogether between index and read.