我遇到了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