php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #43239 read/write for __get and __set like in C#
Submitted: 2007-11-11 00:49 UTC Modified: 2017-12-09 14:32 UTC
Votes:6
Avg. Score:4.2 ± 0.9
Reproduced:6 of 6 (100.0%)
Same Version:4 (66.7%)
Same OS:4 (66.7%)
From: bugs dot php dot net-V29nHf1_z-nsp at cvogt dot org Assigned:
Status: Wont fix Package: Class/Object related
PHP Version: 5.3.0 OS: *
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2007-11-11 00:49 UTC] bugs dot php dot net-V29nHf1_z-nsp at cvogt dot org
Description:
------------
This was already reported 'fixed' in
http://bugs.php.net/bug.php?id=38102
http://bugs.php.net/bug.php?id=37667
but I think the 'fix' is wrong.

It renders __get and __set a LOT less useful then they could be.

__get and __set should provide a means to replace public fields while maintaining the interface.

With the provided 'fix' this is not possible. Code like
$r->Property[] = new Class2();
works fine for Property as a public field but breaks if Property is replaced using __get and __set.

We all agree __get should not return a reference. Instead I think that cases that involve read and write operations like [] and += and .= should equal a call to __get and a subsequent call to __set. More specificially:

$r->Property[] = new Class2();

should equal

$x = $r->__get('Property');
$x[] = new Class2();
$r->__set('Property',$x);

This is exactly the way C# does it. See http://www.geocities.com/csharpfaq/properties.html

Reproduce code:
---------------
class Class1 {
  protected $property = array();
  function __get($name) {
    return $this->property;
  }
}
class Class2 {}
$r = new Class1();
$r->Property[] = new Class2();
$r->Property[] = new Class2();
var_dump($r);

Expected result:
----------------
object(Class1)#1 (1) {
  ["property:protected"]=>
  array(1) {
    [0]=>
    object(Class2)#2 (0) {
    }
    [0]=>
    object(Class2)#3 (0) {
    }
  }
}

Actual result:
--------------
In PHP 5.3.0-dev (cli) (built: Oct 30 2007 08:45:02):

object(Class1)#1 (1) {
  ["property:protected"]=>
  array(0) {
  }
}

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-11-11 15:06 UTC] bugs dot php dot net-V29nHf1_z-nsp at cvogt dot org
The Problem occurs for non-object data types only. string, array, int, float
 [2010-11-18 23:08 UTC] jani@php.net
-Package: Feature/Change Request +Package: *General Issues -PHP Version: PHP 5.3.0 +PHP Version: 5.3.0
 [2010-11-18 23:09 UTC] jani@php.net
-Package: *General Issues +Package: Class/Object related -Operating System: +Operating System: *
 [2017-12-09 14:32 UTC] nikic@php.net
-Status: Open +Status: Wont fix
 [2017-12-09 14:32 UTC] nikic@php.net
The desired behavior can already be achieved by returning from __get() by reference. For simple operations (like +=) we do support desugaring compound assignments into a __get() followed by __set(). However, for array operations this would be very inefficient, as it would require copying the entire array, performing the operation and then replacing the original array with a copy. This is why array operations only work with __get() returning by reference, which allows to do this efficiently.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Tue Nov 24 07:01:24 2020 UTC