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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: bugs dot php dot net-V29nHf1_z-nsp at cvogt dot org
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2025 The PHP Group
All rights reserved.
Last updated: Sun Jan 05 05:01:28 2025 UTC