我有一个已经定义的闭包,我想在执行它时注入代码.这是一个例子:
$predefined = "print 'my predefined injected code<br />';";
$closure = function () {
print 'hello<br />';
};
call_user_func_array($closure, array());
// output : hello
Run Code Online (Sandbox Code Playgroud)
我想混合2个代码:一个预定义的代码和一个代码的代码.修改后,我希望我的闭包看起来像这样
$closure = function () {
print 'my predefined injected code<br />';
print 'hello<br />';
};
Run Code Online (Sandbox Code Playgroud)
在执行之前是否可以在闭包中插入一些代码?
注意:我不能使用将代码作为字符串的"create_function",因此可以轻松修改.闭包已经定义并以某种方式定义(通过一个带回调arg而不是字符串arg的函数).
谢谢你的帮助.
编辑:
这是解决方案
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();
Run Code Online (Sandbox Code Playgroud)
它呈现
something to say
Run Code Online (Sandbox Code Playgroud)
代替
something
Run Code Online (Sandbox Code Playgroud)
你不能直接注射它.但是,你可以包装它.
$newClosure = function() use ($closure) {
print 'my predefined injected code<br />';
$closure();
};
Run Code Online (Sandbox Code Playgroud)
此外,没有必要使用,call_user_func_array因为你没有传递任何参数.打电话吧$closure();
此外,您可以构建一个包装器来获取新的闭包:
$creator = function($closure) {
return function() use ($closure) {
print 'my predefined injected code<br />';
$closure();
};
};
$newClosure = $creator($closure);
$newClosure();
Run Code Online (Sandbox Code Playgroud)