Pitchinnate
Pitchinnate

Reputation: 7556

Protected Array elements after Object to Array

I just came across something weird. I have a class that is similar to this:

class Test {
    public $id;
    public $name;
    public $details;

    private $hidden;
    private $otherhidden;

    public function __construct() {
         $this->id = 1;
         $this->name = 'test';
         $this->details = 'test';
         $this->hidden = 1;
         $this->otherhidden = 1;
    }

    public function toArray() {
        $array = (array) $this;
        print_r($array);
        $array['Testhidden'] = 2;
        $array['Testotherhidden'] = 2;
        unset($array['details']);
        unset($array['Testhidden']);
        unset($array['Testotherhidden']);
        print_r($array);
        return $array;
    }
}

If I create an instance of a Test, $test = new Test; and then run $array = $test->toArray(); the two array's printed out are:

Array
(
    [id] => 1
    [name] => test
    [details] => test
    [Testhidden] => 1
    [Testotherhidden] => 1
)
Array
(
    [id] => 1
    [name] => test
    [Testhidden] => 1
    [Testotherhidden] => 1
)

So it lets me unset the details keyed item in the array, but it won't let me modify the values or the unset the values in the elements that were private in the object. Any ideas for why it won't let me modify the values of the array? Obviously there is some type of inheritance being passed from the object to the array.

EDIT

If I use get_object_vars() instead of (array) I am able to modify the private elements. So I have a work around, but it would still be nice to know why this happens.

Upvotes: 0

Views: 2022

Answers (3)

Orangepill
Orangepill

Reputation: 24645

var_dump will show you the answer. The Array keys for protected properties are turning into "\0Test\0otherhidden" and "\0Test\0hidden". print_r is masking this fact from you.

Upvotes: 0

Jon
Jon

Reputation: 437336

The behavior you see is because when casting an object to an array like that the keys of the arrays that correspond to non-public properties are prefixed with unprintable "magic" strings.

The real keys inside $array are not Testhidden and Testotherhidden. You can easily see that with

print_r(array_map('urlencode', array_keys($array)));

I randomly picked urlencode as a very convenient way of transforming unprintable characters to printable representations, but of course any other function with that property would serve as well.

Upvotes: 2

brenjt
brenjt

Reputation: 16297

This post will answer your questions.

http://www.vancelucas.com/blog/get-only-public-class-properties-for-current-class-in-php/

But basically you get the properties because of the scope in which get_object_vars() is called. But if you change the scope as outlined in the post you should get the results you are looking for.

public function toArray()
{
    $getFields = function($obj) { return get_object_vars($obj); };
    return $getFields($this);
}

Upvotes: 0

Related Questions