要理解我为什么要这样做,请阅读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()
等,但它不起作用。我无法找到解决这些问题的方法。
任何解决方案都应该与原始数组一起使用,而不是创建副本并替换原始数据。
答案 0 :(得分:3)
你可以尝试用array_splice()
删除它,如果你知道它的偏移量(foreach (...) { $offset++; ... }
),但是将数据存储在这样的数组中,确实不是一个好主意。您应该使用foreach将这些对象转换为数组:
foreach ( $obj as $key => $value )
$array[$key] = $value;
答案 1 :(得分: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。耶!