yii绑定onEndRequest事件的bug
yii在CListIterator中使用引用,导致迭代在特殊情况下会出现BUG
1 2 3 4 5 6 7 8 9 10 11 | public function actionIndex() { $data = array('a', 'b', 'c'); $a = new CList($data); foreach ($a as $k => $v) { if ($k == 0) { unset($a[0]); } echo $v; } } |
如果预先不知道这个情况,很容易出现问题,框架中也有这个问题,看一段代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public function setGlobalState($key,$value,$defaultValue=null) { // ... if($this->_stateChanged!==$changed) $this->attachEventHandler('onEndRequest',array($this,'saveGlobalState')); } // ... /** * Saves the global state data into persistent storage. * @see getStatePersister * @throws CException if the state persister is not available */ public function saveGlobalState() { if($this->_stateChanged) { $this->_stateChanged=false; $this->detachEventHandler('onEndRequest',array($this,'saveGlobalState')); $this->getStatePersister()->save($this->_globalState); } } |
1 2 3 4 5 6 7 8 9 10 11 12 | public function raiseEvent($name,$event) { $name=strtolower($name); if(isset($this->_e[$name])) { foreach($this->_e[$name] as $handler) { // ... } } // ... } |
当runtime目录被清空时,onEndRequest事件触发saveGlobalState动作,在操作的过程中却又解除了saveGlobalState动作的绑定。这会导致raiseEvent事件的时候,原来N个动作变成N-1个动作,但是计算器还是N个,就会下标越界。
向官方提交了这个BUG,想修正的话可以先注释掉这行:
1 | $this->detachEventHandler('onEndRequest',array($this,'saveGlobalState')); |
没有评论▼