1

要了解我为什么要问这个问题,请阅读内容及其下方的评论。考虑以下代码:

$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;
            }
        }
    }
}

现在,我可以做(演示)

$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()等,但它不起作用。我找不到解除这些的方法。

任何解决方案都应该使用原始数组,而不是创建副本并替换原始数组。

4

2 回答 2

3

array_splice()如果您知道它的偏移量 ( ),您可以尝试使用 删除它foreach (...) { $offset++; ... },但是将数据存储在这样的数组中确实不是一个好主意。您应该使用 foreach 将这些对象转换为数组:

foreach ( $obj as $key => $value )
    $array[$key] = $value;
于 2012-10-11T19:34:09.793 回答
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。耶!

于 2012-10-11T20:58:46.343 回答