Skip to content
Advertisement

PHP # Accessing protected or private Variables of class by reference intended or a bug?

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
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement