使用真正的关闭,我们可以做,
function foo(&$ref) { $inFn = function() use (&$ref) { $ref = 42; }; $inFn(); }
如果我们更换,
$inFn = function(...
同
$inFn = create_function(...
有没有(简单和干净)的方式做同样的事情?通过引用引用包含范围的变量,而不将它明确地传递给$inFn?
我遇到了
this answer to another question,这激发了我以下想法.我没有大量测试它,我确信它可以改进(并且执行程序调用的需要是一个耻辱),但它似乎解决了我的问题.
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_body) { $inst = new self($use,$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,'<br>';
哪个返回:
06002
或者像这样:
function bar() { $x = 0; echo 'x is ','<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 ','<br>'; } bar();
哪个返回:
06004