【问题标题】:Using __set with arrays solved, but why?使用 __set 解决了数组,但为什么呢?
【发布时间】:2010-11-30 04:16:49
【问题描述】:

经过一些研究,我最终找到了一个我很快就会在这里提出的问题的答案;如何通过 PHP 中的 __get__set 魔术方法处理数组?每当我尝试使用 $object->foo['bar'] = 42; 之类的东西设置值时,它似乎都会默默地丢弃它。

无论如何,答案很简单; __get 方法只需要通过引用返回。并且在它前面扔了一个 & 符号后,果然成功了。

我的问题实际上是为什么?我似乎无法理解为什么这是有效的。 __get 按引用返回对 __set 处理多维数组有何影响?

编辑:顺便说一下,运行 PHP 5.3.1

【问题讨论】:

  • 似乎在 PHP 5.2.x 中使 __get 返回引用没有帮助。

标签: php overloading getter-setter magic-methods


【解决方案1】:

在 PHP 中,当您从一个函数返回一个值时,您可以考虑复制该值(除非它是一个类)。在__get 的情况下,除非您返回要编辑的实际内容,否则所有更改都会对副本进行,然后丢弃。

【讨论】:

  • 啊,所以在设置值的过程中,在调用__set之前,调用__get来检索(或检查)对象变量的存在?
  • $object->foo['bar'] = 42; 从不调用 set。当您执行 $object->key = $value 之类的操作时调用 Set,但当您执行 $object->key[$key2] = $value 时不会调用。这是因为$object->key[$key2] 是使用__get 解析然后更改的。所以你可以把它想象成$magic_get_value = $value
【解决方案2】:

在这种特殊情况下,__set 实际上并没有被调用。如果你分解它发生的事情,它应该更有意义:

$tmp = $object->__get('foo');
$tmp['bar'] = 42

如果__get 没有返回引用,则不是将 42 分配给原始对象的 'bar' 索引,而是分配给 副本 的 'bar' 索引原始对象。

【讨论】:

    【解决方案3】:

    也许更清楚:

    //PHP will try to interpret this:
    $object->foo['bar'] = 42
    
    //The PHP interpreter will try to evaluate first 
    $object->foo
    
    //To do this, it will call 
    $object->__get('foo')
    // and not __get("foo['bar']"). __get() has no idea about ['bar']
    
    //If we have get defined as &__get(), this will return $_data['foo'] element 
    //by reference.
    //This array element has some value, like a string: 
    $_data['foo'] = 'value';
    
    //Then, after __get returns, the PHP interpreter will add ['bar'] to that
    //reference.
    $_data['foo']['bar']
    
    //Array element $_data['foo'] becomes an array with one key, 'bar'. 
    $_data['foo'] = array('bar' => null)
    
    //That key will be assigned the value 42
    $_data['foo']['bar'] = 42
    
    //42 will be stored in $_data array because __get() returned a reference in that
    //array. If __get() would return the array element by value, PHP would have to 
    //create a temporary variable for that element (like $tmp). Then we would make 
    //that variable an array with $tmp['bar'] and assign 42 to that key. As soon 
    //as php would continue to the next line of code, that $tmp variable would 
    //not be used any more and it will be garbage collected.
    

    【讨论】:

      猜你喜欢
      • 2019-05-27
      • 2022-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多