0

我有一个相当复杂的 PHP 应用程序,但 XDebug 帮助我将问题追踪到了一个我不再了解 PHP 的地步。我试图详细说明问题的相关核心。

有一个类层次结构 ModelCore->Model->LMC->MC。在 LMC 中有一个 insert() 方法,它具有以下代码行:

if($this->createEntry($mKey)) return $this->getEntry($mKey);

getEntry方法也在 LMC 中定义:

function getEntry($mKey){
   if(array_key_exists($mKey, $this->aItemList) || $this->createEntry($mKey)) return $this->aItemList[$mKey];
   return false;
}

createEntry在 LMC 中是抽象的,在 MC 中定义:

function createEntry($mKey){
   if(array_key_exists($mKey, $this->aItemList) && ($this->aItemList[$mKey] instanceof LCI))
      return false;
   $this->aItemList[$mKey] = new $this->sItemClass($this,$mKey,(!array_key_exists($mKey,$this->aData))? LCI::Appended : LCI::Unread);
   return ($this->aItemList[$mKey] instanceof LCI);
}

LCI 是与上面显示的树无关的另一个类。sItemClass是 LCI 的适当子类。那么发生了什么?

createEntry应该返回false,如果$this->aItemList已经有相同键的条目,它是 LCI 类型的。否则它将创建这样一个条目。考虑到显示的第一行,getEntry只有在已创建此类条目且类型正确时才会调用。然而,其中的条件没有找到条目并且可以重新创建条目,这当然不会导致数组中的第二个条目。

测试中使用的键值是16通过floatval.

有什么想法吗?

4

1 回答 1

0

感谢 John Green,我将数据库的键更改为字符串,并且效果很好。事实上,我正在寻找另一个问题。MC 是一个模型,并作为对视图的引用传递。在一天结束时,对于最初构建的模型和视图中保存的引用,我在 MC->aItemList[16] 中有不同的 LCI 实例值。事实上,LCI 是在没有任何数据的情况下构建的,考虑到 CTOR,这应该是不可能的。但是这个问题也消失了。

得到教训:

  • 在 PHP 中检查浮点数是否相等似乎比通常更麻烦(之前从未见过$a != $a,任何地方!)
  • 使用浮点数时的结果array_key_exists()可能与索引访问不一致[]
  • 使用浮点数作为数组索引可能会产生超出简单错误关联和超出想象的副作用

感谢您检查代码并排除不可能揭示真相的可能性,无论它看起来多么不可能。

于 2012-06-29T09:21:08.823 回答