Explanation
While researching, I created this little code snippet below to get to know php better. The reason why I now create this question is to reach more experienced developers in order to not clog the system too much and don’t bring this further than it has to.
Below is a code example on how to access a private or protected Variable outside the scope the class.
Code Example
This code example will setup $TestVar
to be a reference to the private Variable test::A
inside of the test
class.
<?php class Test { private $A = 123; public function changeA ($Var){ $this->A = $Var; } public function createReference(){ return([&$this->A]); } } $TestClass = new Test(); $TestVar = &$TestClass->createReference()[0];
By either using Test::changeA()
or changing $TestVar
the content of test::A
can be changed.
//Test Current Value var_dump($TestVar); //Change test::A the intended way $TestClass->changeA(321); var_dump($TestVar); //Change it by reference $TestVar = 777; var_dump($TestVar); var_dump($TestClass);
Expected Output:
int 123 int 321 int 777 object(Test)[1] private 'A' => int 777
Result
The reason why I see this as a bug, The manual states in both description and examples:
Members declared protected can be accessed only within the class itself and by inheriting and parent classes.
Members declared as private may only be accessed by the class that defines the member.
for this to not be possible or intended.
Is this a bug, a wrong documentation or simply an error someone has to live with.
Advertisement
Answer
That behaviour is perfectly normal. In fact, if your properties are objects (which are always passed by reference) you don’t even need to create the references explicitly:
class Foo { private Datetime $when; public function __construct() { $this->when = new DateTime('1950-12-31'); } public function getWhen(): DateTime { return $this->when; } } $f = new Foo(); $w = $f->getWhen(); $w->modify('+50 years'); var_dump($w, $f);
object(DateTime)#2 (3) { ["date"]=> string(26) "2000-12-31 00:00:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(13) "Europe/Madrid" } object(Foo)#1 (1) { ["when":"Foo":private]=> object(DateTime)#2 (3) { ["date"]=> string(26) "2000-12-31 00:00:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(13) "Europe/Madrid" } }
This doesn’t contradict the documentation you’ve quoted. The property itself is unreachable:
$f->when; // PHP Fatal error: Uncaught Error: Cannot access private property Foo::$when
References are a different language feature. Perhaps it’s easier to understand with this other example:
function a(){ $local_variable = 1; b($local_variable); echo "b modified a's local variable: $local_variablen"; } function b(&$number) { echo "b can read a's local variable: $numbern"; $number++; } a();
b can read a's local variable: 1 b modified a's local variable: 2