2012-10-11 91 views
1

要理解我爲什麼要這樣做,請閱讀this及其下的註釋。請看下面的代碼:與具有數字字符串鍵的數組混合使用

$obj = new stdClass; 
$obj->{10} = 'Thing'; 

$objArray = (array) $obj; 
var_dump($objArray); 

產地:現在

array(1) { 
    ["10"]=> 
    string(5) "Thing" 
} 

,我無法訪問通過$objArray['10']因爲PHP轉換數字字符串鍵整數密鑰。將數組轉換爲對象時,手冊明確指出「整數屬性不可訪問」。或者他們?

爲了證明文檔錯了,我創建了一個類:

class strKey implements ArrayAccess 
{ 
    private $arr; 
    public function __construct(&$array) 
    { 
     $this->arr = &$array; 
    } 

    public function offsetExists($offset) 
    { 
     foreach ($this->arr as $key => $value) 
     { 
      if ($key == $offset) 
      { 
       return true; 
      } 
     } 
     return false; 
    } 

    public function offsetGet($offset) 
    { 
     foreach ($this->arr as $key => $value) 
     { 
      if ($key == $offset) 
      { 
       return $value; 
      } 
     } 
     return null; 
    } 

    public function offsetSet($offset, $value) 
    { 
     foreach($this->arr as $key => &$thevalue) 
     { 
      if ($key == $offset) 
      { 
       $thevalue = $value; 
       return; 
      } 
     } 

     // if $offset is *not* present... 
     if ($offset === null) 
     { 
      $this->arr[] = $value; 
     } 
     else 
     { 
      // this won't work with string keys 
      $this->arr[$offset] = $value; 
     } 
    } 

    // can't implement this 
    public function offsetUnset($offset) 
    { 
     foreach ($this->arr as $key => &$value) 
     { 
      if ($key == $offset) 
      { 
       //$value = null; 
      } 
     } 
    } 
} 

現在,我可以做(demo)

$b = new strKey($objArray); 

echo $b['10']; // Thing 
$b['10'] = 'Something else'; 

// because the classes works with a reference to the original array, 
// this will give us a modified array: 
var_dump($objArray); 

拼圖的最後一塊是,我怎麼取消設置一個元素其關鍵是數字字符串?我嘗試使用ArrayIterator,key(),next()等,但它不會工作。我無法找到解決這些問題的方法。

任何解決方案應該與原始數組一起工作,而不是創建副本並替換原始數組。

回答

3

如果你知道它的偏移量(foreach (...) { $offset++; ... }),但是將數據存儲在這樣的數組中,你可以試着用array_splice()去除它,這真的不是一個好主意。您應該將這些對象轉換爲數組用foreach:

foreach ($obj as $key => $value) 
    $array[$key] = $value; 
0

繼pozs的建議,這裏的產生offsetUnset()。我還添加了一個新的支持添加數字鍵的offsetSet()

public function offsetUnset($offset) 
{ 
    $off = 0; 

    foreach ($this->arr as $key => $value) 
    { 
     if ($key === $offset) 
     { 
      array_splice($this->arr, $off, 1); 
      return; 
     } 
     $off++; 
    }  
} 

public function offsetSet($offset, $value) 
{ 
    foreach($this->arr as $key => &$thevalue) 
    { 
     if ($key === $offset) 
     { 
      $thevalue = $value; 
      return; 
     } 
    } 

    // if $offset is *not* present... 
    if ($offset === null) 
    { 
     $this->arr[] = $value; 
    } 
    // it's a numeric string key, now we have to hack it 
    else if (strval(intval($offset)) === $offset) 
    { 
     // create new array via loophole: 
     $tempObj = new stdClass; 
     $tempObj->{$offset} = $value; 

     // append to old array (+= doesn't create copies) 
     $this->arr += (array) $tempObj; 
     unset($tempObj); 
    } 
    // we are dealing with a normal key 
    else 
    { 
     $this->arr[$offset] = $value; 
    } 
} 

我已經正式擊敗了PHP。好極了!

相關問題