tibsar February 2016

Getting protected information from an object in PHP

I'm pretty new to PHP and am trying to understand how to access properties of objects.

I have a class called Dog and in it's class I have the following:

class Dog extends Resource {
    protected $_data = array(
        'dog_id' => array(
             'type' => Resource::PROPERTY_TYPE_INTEGER, 
             'value' => null
         ), 
         'owner_id' => array(
             'type' => Resource::PROPERTY_TYPE_INTEGER, 
             'value' => null
         )        
    )
}

Now I'm trying to use this data in a controller.

$drm = DogResouceModel::create(); 
$fido = array_values($drm->find($dog_id))[0]; 

This works and I get the desired Dog object as $fido. How would I get to the owner_id? Using XDebug in Eclipse I can see that the values are all attached to $fido, I just can't seem to figure out how to get to them. I've tried things along the lines of:

$owner_id = $fido["_data"]["owner_id"];  
$owner_id = $fido->_data->owner_id; 

Answers


jbafford February 2016

Because _data is protected, it's not possible to directly access it from outside the Dog or Resource classes. Instead, you should add an accessor to either Dog or Resource (as appropriate) that retrieves the requested data.

class Dog extends Resource {
    public function getOwerId() {
        return $this->_data['owner_id']['value'];
    }
}

You could also force _data to be accessible by hacking it using the Reflection API, but that's really not something you should be doing on production code.


Elias Van Ootegem February 2016

The common way to do this is to implement getter/setter methods:

class Dog extends Resource
{
    protected $data = [];//initialize as before (no need for the underscore)

    public function getOwnerId()
    {
        return $this->data['owner_id']['value'];
    }
    //setter example
    public function setOwnerId($id)
    {
        if (!is_numeric($id)) {
            throw new InvalidArgumentException('Owner id is numeric');
        }
        $this->data['owner_id']['value'] = (int) $id;

        return $this;
    }
}

The rational behind this is that getters and setters allow you to validate data, normalize it and define, in greater levels of detail, how an object should behave if, for example, a value isn't available (ie: if owner_id is null, you might want to throw an exception in some cases).

The fact that you can see them in an XDebug session is simply because the data is set, and XDebug allows you to inspect the state of all objects. It doesn't follow the rules of inheritance in that it can see all values that are in play, regardless of them being private, protected or public. Xdebug is a PHP extension, it's written in C and sits on top of the Zend engine (the PHP internals), it is not bound by the syntax, grammar or whatever else that is part of PHP.

Think of Xdebug as an MRI scanner or X-ray machine: it allows you to see what is going on underneath the skin. It's a tool doctors use, like debuggers are tools that developers use to diagnose problems.

Looking at what you've tried, even if $data were public, neither approach would've worked:

$owner_id = $fido["_data"]["owner_id"];  

The problem here is that this plies that $fido is an array, or an object that implements the ArrayAccess interface. We don't know what Resource looks like, so maybe it does (more on that later).

$ 


Sam Swift 웃 February 2016

OOP Programming PHP

You are using OOP, grats dude (or dudette :P)!

PHP is great for this, however it has it's limitations, for example, accessing properties.
You have used protected $_data = array( /* your info */ );, this means it is only visible to the class and any class that extends this.

For example, if you had these classes:

class Foo 
{
    protected $foo = "Foo";
}

class Bar extends Foo
{
    private $bar = "bar";
}

You could add a function, as such:

public function getFooBar()
{
    return "{$this->foo} {$this->bar}";
}

Inside the Bar class, that simply returns the value of $foo and $bar, meaning if you use this code:

$bar = new Bar();
print $bar->getFooBar(); // prints "Foo bar"

But you cannot do this:

print $bar->foo;
print $bar->bar;

These are seen as private properties of the Bar class and as such cannot be accessed outside of the class.

When you use protected or private properties, if you need to access them outside the class, create a get function for them.

Why does the debugger show the private and protected properties?

When using a debugger such as XDebug, it is designed to show all properties within an object, this is so that the person debugging (you), can see exactly what's in an object and be able to create some sort of functionality to access this if needed. Without this, debugging tools would be rather useless.

I hope this helps you out :P

Post Status

Asked in February 2016
Viewed 2,175 times
Voted 6
Answered 3 times

Search




Leave an answer