yii在CListIterator中使用引用,导致迭代在特殊情况下会出现BUG
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;
}
}
如果预先不知道这个情况,很容易出现问题,框架中也有这个问题,看一段代码:
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);
}
}
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,想修正的话可以先注释掉这行:
$this->detachEventHandler('onEndRequest',array($this,'saveGlobalState'));