在 PHP 闭包中注入代码

发布于 2024-10-19 14:06:09 字数 1630 浏览 0 评论 0原文

我有一个已经定义的闭包,我想在执行它时在其中注入代码。 这是一个示例:

$predefined = "print 'my predefined injected code<br />';";
$closure = function () {
  print 'hello<br />';
};
call_user_func_array($closure, array());
// output : hello

我想混合 2 个代码:预定义的代码和闭包的代码。 修改后,我希望我的闭包看起来像这样

$closure = function () {
  print 'my predefined injected code<br />';
  print 'hello<br />';
};

是否可以在执行之前在闭包中插入一些代码?

注意:我不能使用将代码作为字符串的“create_function”,因此可以轻松修改。闭包已经定义并且以某种方式定义(通过采用回调参数而不是字符串参数的函数)。

感谢您的帮助。


编辑:

解决方案

function hackClosure($closure, $inject_code)
{
    $reflection = new ReflectionFunction($closure);
    $tmp = $reflection->getParameters();
    $args = array();
    foreach ($tmp as $a) array_push($args, '$'.$a->getName() . ($a->isDefaultValueAvailable() ? '=\''.$a->getDefaultValue().'\'' : ''));
    $file = new SplFileObject($reflection->getFileName());
    $file->seek($reflection->getStartLine()-1);
    $code = '';
    while ($file->key() < $reflection->getEndLine())
    {
        $code .= $file->current();
        $file->next();
    }
    $start = strpos($code, '{')+1;
    $end = strrpos($code, '}');
    return create_function(implode(', ', $args), substr($code, $start, $end - $start) . $inject_code);
}

$theClosure = function () { print 'something'; };

$inject_code = "print ' to say';";

$func = hackClosure($theClosure, $inject_code);
$func();

这是它呈现的

something to say

而不是

something

I have an already defined closure and I want to inject code inside when I execute it.
Here is an example:

$predefined = "print 'my predefined injected code<br />';";
$closure = function () {
  print 'hello<br />';
};
call_user_func_array($closure, array());
// output : hello

I want to mix 2 codes : a predefined one and the closure's one.
After modification, I want my closure to look like this

$closure = function () {
  print 'my predefined injected code<br />';
  print 'hello<br />';
};

Is it possible to insert some code in the closure before executing it ?

Note: I can not use "create_function" that take the code as a string, so can be modified easily. The closures are already defined and are defined in a certain way (through a function that take a callback arg, not a string arg).

Thanks for your help.


EDIT:

Here is the solution

function hackClosure($closure, $inject_code)
{
    $reflection = new ReflectionFunction($closure);
    $tmp = $reflection->getParameters();
    $args = array();
    foreach ($tmp as $a) array_push($args, '

It renders

something to say

instead of

something
.$a->getName() . ($a->isDefaultValueAvailable() ? '=\''.$a->getDefaultValue().'\'' : '')); $file = new SplFileObject($reflection->getFileName()); $file->seek($reflection->getStartLine()-1); $code = ''; while ($file->key() < $reflection->getEndLine()) { $code .= $file->current(); $file->next(); } $start = strpos($code, '{')+1; $end = strrpos($code, '}'); return create_function(implode(', ', $args), substr($code, $start, $end - $start) . $inject_code); } $theClosure = function () { print 'something'; }; $inject_code = "print ' to say';"; $func = hackClosure($theClosure, $inject_code); $func();

It renders

instead of

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

篱下浅笙歌 2024-10-26 14:06:10

你不能直接注入它。但是,您可以将其包裹起来。

$newClosure = function() use ($closure) {
    print 'my predefined injected code<br />';
    $closure();
};

此外,无需使用 call_user_func_array 因为您没有传递任何参数。只需调用 $closure();

另外,您可以构建一个包装器来获取新的闭包:

$creator = function($closure) {
    return function() use ($closure) {
        print 'my predefined injected code<br />';
        $closure();
    };
};

$newClosure = $creator($closure);
$newClosure();

You can't directly inject it. However, you can wrap it.

$newClosure = function() use ($closure) {
    print 'my predefined injected code<br />';
    $closure();
};

Also, there's no need to use call_user_func_array since you're not passing any arguments. Just call $closure();

Also, you could build a wrapper to get a new closure:

$creator = function($closure) {
    return function() use ($closure) {
        print 'my predefined injected code<br />';
        $closure();
    };
};

$newClosure = $creator($closure);
$newClosure();
几味少女 2024-10-26 14:06:10

也许是这样的:

$closure = function($optionalcode = null) {
    print('blah blah blah');
    if (!is_null($optionalcode)) { eval($optionalcode); }
    print('blah blah blah');
}

$closure("print('yoohoo!');");

然而,eval()是邪恶的,应该不惜一切代价避免。

perhaps something like this:

$closure = function($optionalcode = null) {
    print('blah blah blah');
    if (!is_null($optionalcode)) { eval($optionalcode); }
    print('blah blah blah');
}

$closure("print('yoohoo!');");

However, eval() is evil and should be avoided at all costs.

寄居者 2024-10-26 14:06:10

这不是您要找的吗? http://php.net/manual/en/function.eval.php

Is't this what you are looking for ? http://php.net/manual/en/function.eval.php

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文