How to get the number of parameters of a run-time determined callable?
I created a shorter version that works much like call_user_func() and tested it on all different types in the PHP manual for callbacks/callables. This way you can use it almost anywhere. call_user_func() doesn't take objects only, and it didn't make sense to me that this function should either, since it is only handling callbacks.
Tests and suggestions on how to use it are included below and I hope this helps:
function getNrOfParams($callable)
{
$CReflection = is_array($callable) ?
new ReflectionMethod($callable[0], $callable[1]) :
new ReflectionFunction($callable);
return $CReflection->getNumberOfParameters();
}
The test and its result in its entirety:
<?php
class Smart
{
public function __invoke($name)
{
}
public function my_callable($one, $two, $three)
{
}
public static function myCallableMethod($one, $two)
{
}
public static function who()
{
echo "smart the parent class";
}
}
class Smarter extends Smart
{
public static function who()
{
echo "smarter";
}
}
function my_ca($one)
{
}
function getNrOfParams($callable)
{
$CReflection = is_array($callable) ? new ReflectionMethod($callable[0], $callable[1]) : new ReflectionFunction($callable);
return $CReflection->getNumberOfParameters();
}
// Test 1 Callable Function
echo "Test 1 - Callable function:" . getNrOfParams('my_ca');
// Test 2 Static method
echo " Test 2 - Static class method:" . getNrOfParams(array('Smart', 'myCallableMethod'));
// Test 3 Object method
$smart = new Smart();
echo " Test 3 - Object method:" . getNrOfParams(array($smart, 'my_callable'));
// Test 4 Static method call (As of PHP 5.2.3)
//echo " Test 4 - Static class method call:" . getNrOfParams('Smart::myCallableMethod');
// Calling a static method this way does not work in ReflectionFunction.
// However, Test 2 provides a solution.
// Test 5 Relative static method (As of PHP 5.3.0)
//echo " Test 5 - Relative static class method:" . getNrOfParams(array('Smarter', 'parent::who'));
// Calling a relative static method doesn't work either. ReflectionMethod lacks support.
// All other tests work.
// Tesy 6 __invoke
echo " Test 6 - __invoke:" . getNrOfParams(array($smart, '__invoke'));
// Test 7 Closure
$closure = function($one, $two, $three)
{
// Magic
};
echo " Test 7 - Closure:" . getNrOfParams($closure);
TL;DR I don't think so. You need to check for all callable types if you want a generic solution.
The following function can be used to get a ReflectionFunctionAbstract
instance for any generic callable in PHP:
function reflectionOf(callable $callable): ReflectionFunctionAbstract
{
if ($callable instanceof Closure) {
return new ReflectionFunction($callable);
}
if (is_string($callable)) {
$pcs = explode('::', $callable);
return count($pcs) > 1 ? new ReflectionMethod($pcs[0], $pcs[1]) : new ReflectionFunction($callable);
}
if (!is_array($callable)) {
$callable = [$callable, '__invoke'];
}
return new ReflectionMethod($callable[0], $callable[1]);
}
Then it is possible to get the number of parameters as follows:
reflectionOf($func)->getNumberOfParameters();
Hope this helps to someone. This answer might be late to the party, but none of the other solutions provide a full coverage for generic callables.