5

If I have a public class method that is returning a reference to a non-visible (private or protected) property, I can use that reference to gain direct access:

PHP code

class A
{
    private $property = 'orange';

    public function &ExposeProperty()
    {
        return $this->property;
    }

    public function Output()
    {
        echo $this->property;
    }
}

$obj = new A();

# prints 'orange'
$obj->Output();

$var = &$obj->ExposeProperty();
$var = 'apple';

# prints 'apple'
$obj->Output();

Is there a reasoning behind this functionality in PHP? Or is it just a design oversight, failing to keep track of access violations through references?

It obviously comes in handy when you want to achieve something like:

PHP code

$this->load->resource();

Where load is an object that modifies given properties of $this. But apart from this shortcut, I don't see many possible uses which wouldn't be possible with valid OOP patterns otherwise.

John Weisz
  • 30,137
  • 13
  • 89
  • 132

1 Answers1

6

Well, you are explicitly returning a reference to a value. You're locking the front door, but are then opening a side entrance. You are very deliberately taking aim and shooting your own foot here. If $property was an object, and you'd return this object with or without & reference, any modifications to this object would be reflected on $property as well. That's how a reference works, it always modifies the one and only existing value that the reference points to.

Visibility modifiers aren't magic iron clad "protections". There are any number of ways how you can circumvent a private visibility to access and modify the property. They're mostly there as a flag to yourself and other developers that this property should not be accessed directly, it's for internal use and not a publicly sanctioned API. And PHP will slap you on the wrist should you forget that. Nothing more, nothing less.

Also, nothing is really being violated here. Outside code is at no point accessing or modifying $obj->property. That's the only thing private is supposed to prohibit. You're essentially exposing a public API on your object which modifies a private property. Usually this is done with getter and setter functions, but a by-reference API obviously works as well.

deceze
  • 510,633
  • 85
  • 743
  • 889