Php stdClass动态成员-内存耗尽
问题很简单: 我有一个像Php stdClass动态成员-内存耗尽,php,Php,问题很简单: 我有一个像 {a:'A', b:'B'} 我希望它是这样的 {a:'A', new_a:'A', b:'B', new_b:'B'} 使用的代码是: <?php $obj = new stdClass(); $obj->a = 'A'; $obj->b = 'B'; foreach($obj as $field=>$value) { $obj->{'new_'.$field} = $value; } 第9行是: $obj->{'
{a:'A', b:'B'}
我希望它是这样的
{a:'A', new_a:'A', b:'B', new_b:'B'}
使用的代码是:
<?php
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
foreach($obj as $field=>$value)
{
$obj->{'new_'.$field} = $value;
}
第9行是:
$obj->{'new_'.$field} = $value
我确实有其他方法来解决这个问题,但我不明白为什么这个特定的代码会产生这个错误。
有人知道这个错误的原因吗,最后是一个解释。
谢谢大家! 问题是,在迭代源对象属性时,会向源对象添加更多属性,因此
foreach
循环永远不会结束
通过向循环添加var\u dump
调用,可以看到这种情况:
foreach($obj作为$field=>$value)
{
$obj->{'new.'.$field}=$value;
var_dump($obj);
}
结果:
对象(stdClass)#1(29){
[“a”]=>
字符串(1)“A”
[“b”]=>
字符串(1)“B”
[“新的”]=>
字符串(1)“A”
[“新的”]=>
字符串(1)“B”
[“新的”]=>
字符串(1)“A”
[“新建”]=>
字符串(1)“B”
[“新的”]=>
...
而是创建一个新对象并替换旧对象:
$obj=newstdclass();
$obj->a='a';
$obj->b='b';
$newObj=新stdClass();
//复制旧属性
foreach($obj作为$field=>$value){
$newObj->{$field}=$value;
}
//创建新属性
foreach($obj作为$field=>$value){
$newObj->{'new.'.$field}=$value;
}
甚至:
$obj=newstdclass();
$obj->a='a';
$obj->b='b';
$newObj=新stdClass();
//复制旧属性并创建新属性
foreach($obj作为$field=>$value){
$newObj->{$field}=$value;
$newObj->{'new.'.$field}=$value;
}
如前所述,您必须创建另一个$obj而不是在循环中使用对象
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$obj2 = new stdClass();
foreach($obj as $field=>$value)
{
$obj2->{$field} = $value;
$obj2->{'new_'.$field} = $value;
}
$obj = $obj2;
echo '<pre>';
var_dump($obj);
$obj=newstdclass();
$obj->a='a';
$obj->b='b';
$obj2=新的stdClass();
foreach($obj作为$field=>$value)
{
$obj2->{$field}=$value;
$obj2->{'new.'.$field}=$value;
}
$obj=$obj2;
回声';
var_dump($obj);
您正在使用同一对象的属性向正在循环的同一对象添加更多数据……要解决这一问题,您可以执行以下操作:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$obj2 = new stdClass();
foreach($obj as $field=>$value)
{
$key = 'new_'.$field;
$obj2->{$field} = $value;
$obj2->{$key} = $value;
}
$obj = clone $obj2;
unset($obj2);
var_dump($obj);
// YIELDS:
object(stdClass)[3]
public 'a' => string 'A' (length=1)
public 'new_a' => string 'A' (length=1)
public 'b' => string 'B' (length=1)
public 'new_b' => string 'B' (length=1)
我不知道为什么会有这么多关于创建第二个对象来解决这个问题的建议。在我看来,最简单的方法就是在循环之前获取字段,这样您只需迭代初始字段集:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
foreach($obj as $field=>$value)
{
$obj->{'new_'.$field} = $value;
}
请参见您的代码卡在无限循环中,因为如果您有:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$objcopy = clone $obj;
foreach($objcopy as $field=>$value)
{
$obj->{'new_'.$field} = $value;
}
在每次迭代中,您将向对象添加一个新位置,并且该位置必须由foreach迭代
您可以克隆原始对象并迭代克隆,在迭代中您可以向原始对象添加新位置
您正在修改循环中的对象,因此循环永远不会结束。请参阅,以获取正在进行的操作的简化示例。在您的第一个对象中,我认为您想说
{a:'a',b:'b'}
(大写b)@iainn:你说得对!谢谢!你可以在一个循环中复制旧属性和新属性。是的,为了清晰起见,我刚刚扩展了代码,我将添加一个简短的版本。这是有效的,询问者指定了stdClass
,但是重要的是要注意,一个实现的\u clone
魔术方法可能会导致这种行为使用其他类时,与预期的不同。@Dan完全正确……您是对的……非常感谢您不必创建其他对象。
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$fields = get_object_vars($obj);
foreach ($fields as $field => $value) {
$obj->{'new_'.$field} = $value;
}
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
foreach($obj as $field=>$value)
{
$obj->{'new_'.$field} = $value;
}
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$objcopy = clone $obj;
foreach($objcopy as $field=>$value)
{
$obj->{'new_'.$field} = $value;
}