I need a method/function that takes “callable” as one of the parameters, but this argument must be restricted to only non-anonymous.
So, when you pass anonymous method/function/invokable class must be thrown InvalidArgumentException;
The effect should be as follows:
class MyClass {
public static function staticMethod() {}
public function method(){}
public function __invoke() {}
}
$anonClass = new class {
public static function staticMethod() {}
public function method(){}
public function __invoke() {}
};
function myFunction() {};
$anonFunction = function() {};
// Function results:
checkCallable('myFunction'); // Ok
checkCallable($anonFunction); // throw InvalidArgumentException('Function cannot be anonymous');
checkCallable(fn() => "Something n"); // throw InvalidArgumentException('Function cannot be anonymous');
// Class results:
$obj = new MyClass();
$anonObj = new $anonClass();
checkCallable(array($obj, 'method')); // Ok
checkCallable(array('MyClass', 'staticMethod')); // Ok
checkCallable($obj); // Ok
checkCallable(array($anonObj, 'method')); // throw InvalidArgumentException('Class cannot be anonymous');
checkCallable(array($anonClass, 'staticMethod')); // throw InvalidArgumentException('Class cannot be anonymous');
checkCallable($anonObj); // throw InvalidArgumentException('Class cannot be anonymous');
- Question: Do my test cases cover all possibilities?
(Excluding create_function() as it is deprecated since 7.2)
I’ve tried to use Reflection, but i don’t know how to get class from array callable using ReflectionMethod since then the property class is string not ReflectionClass.
public static function checkCallable(callable $method)
{
if ($method instanceof Closure) {
$ref = new ReflectionFunction($method);
// @todo As of 8.0+ use ->isAnonymous() instead
if ($ref->name == '{closure}') {
// throw new InvalidArgumentException('Callable method cannot be an anonymous');
}
} else {
if (is_object($method)) {
$ref = new ReflectionClass($method);
self::checkClass($ref);
} else {
$ref = new ReflectionMethod($method[0], $method[1]);
// Since then $ref has 2 properties: $class and $name.
// Both are string, i could assume (Can I?) that method isn't anonymous since is declared in class, but how to check the Class, i Cannot use my checkClass method, since property is string instead of ReflectionClass()
self::checkClass($ref->class); // ERROR :C
}
}
}
private static function checkClass(ReflectionClass $class)
{
if ($class->isAnonymous()) {
throw new InvalidArgumentException('Callable class cannot be an anonymous');
}
}
Any suggestion will be appreciated.