Sara Fuerst
Sara Fuerst

Reputation: 6068

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; 

Upvotes: 1

Views: 106

Answers (3)

Elias Van Ootegem
Elias Van Ootegem

Reputation: 76395

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).

$owner_id = $fido->_data->owner_id; 

This is closer to what you could do if _data were public, but only if its value were an object, too (which it isn't, it's an array).

So what should you write if $_data were public? Well simply this:

$ownerId = $fido->_data['owner_id']['value'];//to get the value
$ownerIdArray = $fido->_data['owner_id'];//will be an array

If Resource implements the ArrayAccess interface, chances are it relies on the $_data property, and returns the values for each key. In that case you might be able to write:

$ownerId = $fido['owner_id']

or even iterate over the object:

foreach ($fido as $propery => $value) {
    //do stuff
}

Check the PHP documentation for details on the ArrayAccess interface

Upvotes: 3

anon
anon

Reputation:

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

Upvotes: 1

jbafford
jbafford

Reputation: 5668

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.

Upvotes: 1

Related Questions