Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to create a named function from a closure?

Tags:

php

In PHP, you can have named functions like this:

function foo()
{
   return "bar";
}

And you can have Closures like this:

$foo = function() {
    return "bar";
};

Closures are awesome and easy to create, but unfortunately a library I need to use really wants a named function. Is it possible to create a named function from closures dynamically? I.e. not defining all functions in code ahead of time, but more like a register_function($name, callable $closure).

I am aware of create_function, but that one takes a PHP string as function body and just evals it, which is not what I'm looking for.

like image 497
Bert Peters Avatar asked Aug 19 '16 15:08

Bert Peters


People also ask

How does a function create a closure?

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function.

What's the difference between closure and function?

Difference between Function and ClosureFunction is declared using func keyword whereas Closure doesn't have func keyword. Function has always name but Closure doesn't have. Function doesn't have in keyword but closure has in the keyword.

Are C functions closures?

Although C was created two decades after Lisp, it nonetheless lacks support for closures.

What would happen if I remove the closure feature from JavaScript?

If JavaScript did not have closures, then more states would have to be passed between functions explicitly, making parameter lists longer and code noisier. So, if you want a function to always have access to a private piece of state, you can use a closure.


2 Answers

You can create global array with callbacks. Add to this global array by register_func($name, $callback) and call function by call_func($name, $parameter1, $parameter2, ...).

Without using eval I think this is not possible to create named function from callback.

like image 187
ventaquil Avatar answered Sep 30 '22 18:09

ventaquil


I managed to create one using evil eval, ReflectionClass and SuperClosure library.

Here's my code:

<?php

function register_function(string $name, Closure $closure)
{
    $serializedBody = (new SuperClosure\Serializer)->serialize($closure);

    $obj = unserialize($serializedBody);
    $reflection = new ReflectionClass($obj);
    $property = $reflection->getProperty('data');
    $property->setAccessible(true);
    $data = $property->getValue($obj);
    $body = preg_replace('/^function \(/', "function {$name} (", $data['code']);

    eval($body);
}

$closure = function($a = 1, $b = 2, $c = 3) {
    var_dump(compact('a', 'b', 'c'));
};

register_function('test', $closure);

var_dump(function_exists('test')); // true

test(13, 2, 3);
// array(3) {
//   ["a"]=>
//   int(13)
//   ["b"]=>
//   int(2)
//   ["c"]=>
//   int(3)
// }
like image 35
Skysplit Avatar answered Sep 30 '22 18:09

Skysplit