Skip to content

Instantly share code, notes, and snippets.

@conroyp
Created January 6, 2020 11:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save conroyp/2f63a3635b09f40bbb6e48b478b09fca to your computer and use it in GitHub Desktop.
Save conroyp/2f63a3635b09f40bbb6e48b478b09fca to your computer and use it in GitHub Desktop.
func_get_args extended to include default parameters
if (!function_exists('func_get_args_with_defaults')) {
/**
* Get all function arguments, including defaults.
* An issue with func_get_args is that it doesn't include default
* values. This leads to cases where we'd expect cache re-use, but are
* seeing cache misses, e.g:
* $foo->getStuff('category');
* $foo->getStuff('category', 1, 100);
*
* function getStuff($type, $page = 1, $limit = 100)
*
* Using func_get_args to generate a cache key here will generate a different
* key on each call, despite the values of $page and $limit being the same.
* This function uses reflection to work out the full param list.
*
* Usage:
* $args = func_get_args_with_defaults([$this, __FUNCTION__], func_get_args());
*/
function func_get_args_with_defaults(callable $fn, $data = []) : array
{
if (is_string($fn) || $fn instanceof \Closure) {
$reflection = new \ReflectionFunction($fn);
} elseif (is_array($fn)) {
if (is_object($fn[0])) {
$class = new \ReflectionObject($fn[0]);
} else {
// assume string
$class = new \ReflectionClass($fn[0]);
}
$reflection = $class->getMethod($fn[1]);
}
$args = [];
foreach ($reflection->getParameters() as $i => $parameter) {
$name = $parameter->getName();
if (isset($data[$i])) {
$args[$name] = $data[$i];
} else {
$args[$name] = $parameter->isDefaultValueAvailable() ?
$parameter->getDefaultValue() : null;
}
}
return $args;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment