Last active
November 4, 2021 16:53
-
-
Save kmuenkel/8b926c398c22d7641ef1e99bb8c2508a to your computer and use it in GitHub Desktop.
Laravel Request Parameter Filtering: Remove request parameters not defined in the request ruleset, if there is one. Returns false if parameters were attempted, but none were permitted.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Requests; | |
class Request extends FormRequest | |
{ | |
/** | |
* @return bool | |
*/ | |
public function filterFields() | |
{ | |
//Dot notation makes it possible to parse nested values without recursion | |
$original = array_dot($this->all()); | |
$filtered = []; | |
//If there are no rules, accept any input | |
$rules = collect($this->rules()); | |
if ($rules->isEmpty()) { | |
return true; | |
} | |
//Make room for tokens being placed as a URL query parameter, and Fractal includes | |
$exceptions = [ | |
self::TOKEN_NAME => 'string', | |
self::INCLUDE_NAME => 'string', | |
camel_case(self::ADMIN_TOKEN_NAME) => 'string', | |
snake_case(self::ADMIN_TOKEN_NAME) => 'string' | |
]; | |
$keys = $rules->keys()->merge(array_keys($exceptions)); | |
$rules = $rules->merge($exceptions); | |
$rules->each(function ($rules, $key) use ($original, $keys, &$filtered) { | |
//Allow for array or pipe-delimited rule-sets | |
if (is_string($rules)) { | |
$rules = explode('|', $rules); | |
} | |
//In case a rule requires an element to be an array, look for nested rules | |
$nestedRules = $keys->filter(function ($otherKey) use ($key) { | |
return (strpos($otherKey, "$key.") === 0); | |
}); | |
//If the input must be an array, default missing nested rules to a wildcard | |
if (in_array('array', $rules) && $nestedRules->isEmpty()) { | |
$key .= ".*"; | |
} | |
foreach ($original as $dotIndex => $element) { | |
//fnmatch respects wildcard asterisks | |
if (fnmatch($key, $dotIndex)) { | |
//array_set respects dot-notation, building out a normal array | |
array_set($filtered, $dotIndex, $element); | |
} | |
} | |
}); | |
//Replace all input values with the filtered set | |
$this->replace($filtered); | |
//If field changes were attempted, but non were permitted, false here may indicate a 403 if used in authorize() | |
return (empty($original) || !empty($this->all())); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment