Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type hinting when calling arbitrary functions (closures) in PHP

Tags:

closures

php

Silex PHP microframework does a callback injection based on the automatic type hinting. For example, in Silex one can supply a Closure argument with arbitrary arguments like so:

$app->get('/blog/show/{postId}/{commentId}', function ($commentId, $postId) {
    //...
});
$app->get('/blog/show/{id}', function (Application $app, Request $request, $id) {
    //...
});
// following works just as well - order of arguments is not important
$app->get('/blog/show/{id}', function (Request $request, Application $app, $id) {
    //...
});

How do I do this? I'm not interested in getting parameter types as strings. I am looking for a "no strings" fully automatic solution. In other words,

  1. For a number of possible arguments:

    $possible_arguments = [
        new Class_A(), 
        new Class_B(), 
        new Class_C(), 
        new Another_Class, 
        $some_class
    ];
    
  2. For a closure with any number of arbitrary arguments, that can only include those defined above only once:

    $closure = function (Class_B $b, Another_Class, $a) {
        // Do something with $a and $b
    };
    
  3. I need to get only matching arguments in order to call the closure with them:

    // $arguments is now [$possible_arguments[1], $possible_arguments[3]]
    call_user_func_array($closure, $arguments);
    
like image 790
sanmai Avatar asked Feb 18 '23 03:02

sanmai


1 Answers

My guess would be using reflection.

http://php.net/manual/en/class.reflectionparameter.php

Super simple example:

function pre($var)
{
    echo '<pre>' . var_export($var, true) . '</pre>';
}

interface TestInterface
{
}

class TestClass
{
    public function __construct(TestInterface $testArg)
    {
    }
}

function TestFunc(TestInterface $testArg)
{
}

// for a class...

$className = 'TestClass';
$methodName = '__construct';

$argNumber = 0;

$ref = new ReflectionParameter([$className, $methodName], $argNumber);

pre($ref);
pre($ref->getClass());



// for a function...
$funcName = 'TestFunc';
$argNumber = 0;

$ref = new ReflectionParameter($funcName, $argNumber);

pre($ref);
pre($ref->getClass());

Another question I found on stackoverflow might be a better answer to your question: PHP Reflection - Get Method Parameter Type As String

like image 88
Supericy Avatar answered Mar 07 '23 03:03

Supericy