Edit report at http://bugs.php.net/bug.php?id=50892&edit=1
ID: 50892 Comment by: normandiggs at gmail dot com Reported by: EdwardDrapkin at gmail dot com Summary: Protected members of non-congruent children classes are visible Status: Open Type: Feature/Change Request Package: Class/Object related Operating System: Irrelevant PHP Version: 5.3.1 Block user comment: N Private report: N New Comment: Another one example, even without "extends": class Page_Element { protected $name = 'name*'; public function __construct(Page_Element $child = null) { echo $this->name; echo $child->name; } } new Page_Element(new Page_Element(null)); (from http://youtrack.jetbrains.net/issue/WI-4663) So why $child->name can be accessed? It's new object! Previous Comments: ------------------------------------------------------------------------ [2010-05-06 21:58:21] php at b8r dot org Our problem differs slightly from this issue, but I think they share a root cause. Here's a sample of code with the expected outcome. abstract class A { /** * undocumented function * * @return void */ public function __get($propertyName) { $val = $this->$propertyName; echo "Current Value of '{$propertyName}' is '{$val}'\n"; return $val; } public function __set($propertyName, $propertyValue) { echo "Setting Property '{$propertyName}' to '{$propertyValue}'\n"; $this->$propertyName = $propertyValue; } } class B extends A { protected $name; public function populateName($val) { $a = 'name'; $this->$a = $val; } public function testit() { $b = new B(); $b->name = 'internal'; $b->name; } } $two = new B(); $two->name = 'external'; $two->name; $two->testit(); Expected Results: ----------------- Setting Property 'name' to 'external' Current Value of 'name' is 'external' Setting Property 'name' to 'internal' Current Value of 'name' is 'internal' Actual Results: ---------------- Setting Property 'name' to 'external' Current Value of 'name' is 'external' ------------------------------------------------------------------------ [2010-05-06 21:39:30] php at b8r dot org It causes more problems then the original poster notes. We've run into problems using __get and __set. Since php see's the member as "in scope" for both classes, the __get and __set methods don't get called. ------------------------------------------------------------------------ [2010-02-02 03:28:51] col...@php.net At a second glance, it really looks like it is wrong. The visibility check should also be based on the object from which the properties are read. As for my "it works that way in Java" argument, it contradicts the java specifications: http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6.2.1 and hence is invalid. (Thanks oorza for pointing that out) There is no design ground to accept that, it is a bug. The question that remains is: is it worth to fix BC-wise? ------------------------------------------------------------------------ [2010-02-01 14:23:51] johan...@php.net That's a fundamental part of a class based inheritance system.Changing this won't only affect BC but also the fundamental design. ------------------------------------------------------------------------ [2010-02-01 14:15:28] col...@php.net Even though it feels odd, it's how the checks are currently designed. The same applies to i.e. Java. I guess we cannot change things here without introducing nasty and hard to track BC breaks. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at http://bugs.php.net/bug.php?id=50892 -- Edit this bug report at http://bugs.php.net/bug.php?id=50892&edit=1