PHP 5.x和PHP 7 Closure不同行为问题
同样一段闭包代码,PHP 7 ok的,PHP 5.5.11(Windows 开发机器)上却报错,以为是PHP 5 bug,原来是用法不对,记录一下~
原代码(自己写的框架的路由部分)最初是这样写的:
完整代码地址: https://github.com/TF-Joynic/Hydrogen/blob/master/lib/Hydrogen/Route/Router.php
1 public function addRule(RuleInterface $routeRule, \Closure $callback) 2 { 3 4 if (false !== $callbackClosure = $callback->bindTo($routeRule, $routeRule)) { 5 $routeRule->setCallback($callbackClosure); 6 } else { 7 throw new InvalidRuleCallbackException('invalid callback closure specified!'); 8 } 9 10 if (!$routeRule->isTerminable()) { 11 array_unshift($this->_rules, $routeRule); 12 } else { 13 $this->_rules[] = $routeRule; 14 } 15 16 return self::$_instance; 17 }
PHP 7下面跑却是没有问题
但是5.5.11下运行的时候,第4行直接抛 Warning: Cannot bind an instance to a static closure
传进来的 $callback Closure 实际是:
function (Request $request, Response $response) {}
初步判断在5.5环境下PHP认为它是一个static function,而PHP 7下跑的时候可能就认为是普通function
修改代码,以static 的方式bind闭包,php 5下就不报错了:
1 public function addRule(RuleInterface $routeRule, \Closure $callback) 2 { 3 // must bind as a static Closure, otherwise will raise: Warning: Cannot bind an instance to a static closure(v5.x) 4 if (false !== $callbackClosure = \Closure::bind($callback, null, $routeRule)) { 5 $routeRule->setCallback($callbackClosure); 6 } 7 /*if (false !== $callbackClosure = $callback->bindTo($routeRule, $routeRule)) { 8 $routeRule->setCallback($callbackClosure); 9 }*/ else { 10 throw new InvalidRuleCallbackException('invalid callback closure specified!'); 11 } 12 13 if (!$routeRule->isTerminable()) { 14 array_unshift($this->_rules, $routeRule); 15 } else { 16 $this->_rules[] = $routeRule; 17 } 18 19 return self::$_instance; 20 }
具体是不是上述原因有待细究……