【问题标题】:Access $key of an object within a foreach loop在 foreach 循环中访问对象的 $key
【发布时间】:2013-07-07 03:51:01
【问题描述】:

自从我开始在 OOP 中编写更多代码以来,在我看来,我总是遇到“代码样式”问题。我想向现有对象添加一些额外的数据。当我使用数组时,这很容易通过 foreach 实现,因为每个数组项都有自己的键。现在有了对象,我还没有找到一种方法可以使用密钥访问每个项目。

$data_items = $this->model->get_function();
$data_items = (array) $data_items;
foreach ($data_items as $key => $row)
{
      $data_items[$key]['additional_data'] = 'additional_data';                      
}
$data_items = (object) $data_items;

我认为我的代码只是一种变通方法。请有人告诉我是否可以摆脱代码行“$data_items = (array) $data_items;”和“$data_items = (object) $data_items;”。

感谢所有回答我问题的人!

直到现在我还没有意识到我试图实现的目标如此简单:

foreach ($data_items as $row)
{
    $row->additional_data = 'additional_data';
}

【问题讨论】:

  • 对象的 ArrayAccess 接口。 php.net/arrayaccess
  • 是什么阻止您直接在对象上执行foreach
  • 由于你不是试图在没有魔法的情况下将对象转换为字符串或整数,你可以循环遍历对象
  • php.net/manual/en/control-structures.foreach.php - "foreach 仅适用于数组和对象"
  • oop 很棒,但是使用 php stdclass 对象并没有提供任何 oops 的好处。在 php 中,在存储值的集合时,您应该始终偏爱常规数组而不是 stdclass 对象,这仅仅是因为该语言为数组提供了最好的支持。

标签: php arrays oop object foreach


【解决方案1】:

你应该可以做这样的事情:

$data_items = $this->model->get_function();
foreach ($resource_contacts as $key => $row)
{
      $data_items->$key->additional_data = 'additional_data';                      
}

【讨论】:

  • additional_data 不是原始问题中的变量。
  • PHP Notice: Undefined variable: additional_data in php shell code on line 4
  • 感谢您指出这一点,我现在已经删除了额外的“$”,我想我并没有真正注意。 OP 现在已经解决了他的问题,所以我想我的修复现在有点多余了......
【解决方案2】:

从数据处理的角度来看,对象和数组看起来几乎相同。您可以简单地添加另一个对象属性并将数据保存到其中,而无需声明所述属性(在我看来,这是一个缺点,但在您的情况下 - 一个优点)。

数组:

$arr = array();
$arr['additional_data'] = 'foo';

对象:

$obj = new stdClass;
$obj->additional_data = 'bar';

Foreach 将像处理数组键一样处理对象属性。 并且不需要隐式转换。

这是无演员阵容的变体:

$data_items = $this->model->get_function();
foreach ($resource_contacts as $key => $row)
{
      // Note, $data_items->{$key} must be an object, or this will crash.
      // You can check if it is with is_object() and react accordingly
      $data_items->{$key}->additional_data = 'additional_data';                      
}

【讨论】:

    【解决方案3】:

    如果对象实现了Traversable接口(@98​​7654322@、Iterable),比如stdClass,你可以很容易地foreach实例:

    $foo = new stdClass;
    $foo->bar = 'foobar';
    foreach($foo as $property => $value)
    {
        echo '$foo->'.$property.' === '.$value;
        echo $foo->{$property} = 'reassign';
    }
    

    如果不实现这些接口,您仍然可以迭代任何对象,但是:只有公共属性是可见的。
    为了解决这个问题,我倾向于将我的所有属性声明为受保护,并让我的所有数据对象都继承自一个抽象模型,该模型实现了Iterator 接口,所以我不必担心。

    【讨论】:

    • 很好奇。我一直在使用我自己的类,并且从未隐含地声明它们实现了这些属性中的任何一个。 Foreach 刚刚工作。有没有我遗漏的更大的图景?
    • 但是作者不是在尝试foreach一个我们不知道返回什么的方法
    • @MaximKumpan:隐式迭代只允许访问公共属性
    • @RoyalBg:OP 想要获得演员阵容的 rif,如果他不使用 PHP5.4+,那么除了将返回值分配给 tmp var 之外别无选择。
    • 它在一个类里面。但是假设它是:$a = new Class(); $b = $a->method() 应该 $b 获取 stdClass 的实例以便对其进行 foreach 吗?
    【解决方案4】:

    使用引用来修改 foreach 循环中的对象,如果这是您想要实现的目标:

    foreach($objectList as &$obj){
        $obj->newProperty = 'whatever';
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多