2012-10-11 95 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。好极了!

相关问题