使用真正的闭包,我们可以做到,
function foo(&$ref)
{
$inFn = function() use (&$ref)
{
$ref = 42;
};
$inFn();
}
因此修改引用而不必在调用$inFn
时传递它。
如果我们更换,
$inFn = function(...
带
$inFn = create_function(...
是否有任何(简单而干净)的方式来做同样的事情;通过引用引用包含范围的变量,而不将其明确地传递给$inFn
?
答案 0 :(得分:1)
我遇到了this answer to another question,这激励我想出以下内容。我没有对它进行大量测试,我确信它可以改进(并且exec
调用的需要是一种耻辱),但它似乎解决了我的问题。
class create_closure
{
private
$_cb = null,
$_use = array();
public function __construct(array $use, $closure_args, $closure_body)
{
$use_args = implode(array_keys($use), ',');
$this->_cb = create_function(
$use_args.($use_args==='' OR $closure_args==='' ? '' : ',').$closure_args,
$closure_body
);
$this->_use = array_values($use);
}
public static function callback(array $use, $closure_args, $closure_body)
{
$inst = new self($use, $closure_args, $closure_body);
return array($inst, 'exec');
}
public function exec()
{
return call_user_func_array(
$this->_cb,
array_merge($this->_use, func_get_args())
);
}
}
你可以像这样使用它:
function foo(&$ref)
{
$inFn = new create_closure(
array('$ref'=>&$ref),
'',
'$ref=42;'
);
$inFn->exec();
}
$x = 23;
echo 'Before, $x = ', $x, '<br>';
foo($x);
echo 'After, $x = ', $x, '<br>';
返回:
Before, $x = 23 After, $x = 42
或者像这样:
function bar()
{
$x = 0;
echo 'x is ', $x, '<br>';
$z = preg_replace_callback(
'#,#',
create_closure::callback(
array('$x'=>&$x),
'$matches',
'return ++$x;
'
),
'a,b,c,d'
);
echo 'z is ', $z, '<br>';
echo 'x is ', $x, '<br>';
}
bar();
返回:
x is 0 z is a1b2c3d x is 3
答案 1 :(得分:1)
是否有任何(简单和干净)方式来做同样的事情;参考a 通过引用包含范围的变量而不显式 将它传递给$ inFn?
简单回答:不。
create_function
只不过是eval
的包装器,它创建一个伪匿名函数并返回其名称(即'lambda_1'
)。你不能用它创建闭包(那些是内部Closure
类的实例,一个新的语言结构与普通的PHP函数完全不同。我想你是在问这个,因为你想要
如果您可以使用非简单的非清洁解决方案,请查看其他答案。
* )也许这需要一点澄清。 Closure不仅仅意味着匿名函数,它们正是您的问题:记住调用上下文。正常功能无法做到这一点。
答案 2 :(得分:0)
看起来你可以使用$inFn = create_function('&$ref', ...);
。你试过这个吗?