PHP is_callable with Type Definitions

Been searching the PHP documentation and this doesn't seem possible but wanted to check.

Say I have a function like this:

class Utils {
  static function doSomething( Array $input ){
    ...
  }
}

Is is possible to use a inbuilt PHP function like is_callable to check if both the function exists and if the variable I have will be accepted by the type definition in the function.

So:

$varA = array( 'a', 'b', 'c' );
$varB = 'some string';

$functionToCall = array( 'Utils', 'doSomething' );

is_callable( $functionToCall, $varA ) => true;
is_callable( $functionToCall, $varB ) => false;

Of course is_callable cannot be used like this. But can it be done without using a Try Catch?

If not would this be the best way around it?

try {
  Utils::doSomething( 10 )
} catch (TypeError $e) {
  // react here
}

Thanks!

You can use a ReflectionClass to access the ReflectionMethod

With the ReflectionMethod you can access the ReflectionParameter and check the type or the class of the parameter

try{
    $method = new ReflectionMethod('Utils', 'doSomething');
    if(!$method->isStatic()){
        $methodOk = false;
    }

    foreach($method->getParameters() as $parameter){
        //Choose the appropriate test
        if($parameter->getType() != $varA || !is_a($varA ,$parameter->getClass()->getName())){
            $methodOk = false;
        }
    }
}
catch(ReflectionException $ex){
    $methodOk = false;
}

Reference : reflectionparameter and reflection

You can use ReflectionFunction

function someFunction(int $param, $param2) {}

$reflectionFunc = new ReflectionFunction('someFunction');
$reflectionParams = $reflectionFunc->getParameters();
$reflectionType1 = $reflectionParams[0]->getType();
$reflectionType2 = $reflectionParams[1]->getType();

echo $reflectionType1;
var_dump($reflectionType2);

Result:

int
null

reference : http://php.net/manual/en/reflectionparameter.gettype.php

It sounds like you're approaching this from the wrong angle.

In your example use-case, it looks like you want to test that the Utils::doSomething() method both exists and accepts the parameters you're expecting to receive.

The typical way of doing this is using an interface.

In your example, you would have an interface like this:

interface utilsInterface
{
    public static function doSomething(Array $input);
}

Your Utils class could then simply be modified to implement this interface:

class Utils implements utilsInterface
{
     public static function doSomething(Array $input)
     {
          //....
     }
}

Now all you need to do in order to check that the class meets your requirements is to check if it implements the interface:

if (Utils::class instanceof utilsInterface) {
    // now we know that we're safe to call Utils::doSomething() with an array argument.
}