'How to programmatically find public properties of a class from inside one of it's methods

I've got a class Foo with public and protected properties. Foo needs to have a non-static method, getPublicVars() that returns a list of all the public properties of Foo (this is just an example, I know from outside the Foo object calling get_object_vars() will accomplish this and there is no need for my getPublicVars() method).

Note: This must also return dynamically declared properties assigned at runtime to the class instance (object) that aren't defined in the class's definition.

Here's the example:

class Foo{
    private $bar = '123';
    protect $boo = '456';
    public   $beer = 'yum';

   //will return an array or comma seperated list
   public function getPublicVars(){
      // thar' be magic here...
   } 
}

 $foo = new Foo();
 $foo->tricky = 'dynamically added var';

 $result = $foo->getPublicVars();  
 var_dump($result); // array or comma list with 'tricky' and 'beer'   

What is the most concise way to get the only the public properties of an object from inside a class's own methods where both public and protected are visible?

I've looked at:

But this doesn't seem to address my question as it points to using get_object_vars() from outside the object.



Solution 1:[1]

As you already realized, PHP's build in get_object_vars is scope-sensitive. You want the public object properties only.

So from that function to the public variant is not a large step:

function get_object_public_vars($object) {
    return get_object_vars($object);
}

Calling this get_object_public_vars will give you only the public properties then because it is place out of scope of the current object.

If you need more fine-grained control, you can also make use of the ReflectionObject:

(new ReflectionObject($this))->getProperties(ReflectionProperty::IS_PUBLIC);

Which has the benefit that you don't need to introduce another function in the global namespace.

Solution 2:[2]

Does not work with php version >=7
As such, I can't really recommend solution any longer.
Use reflection instead

To get the public properties from within the class

$publicProperties = call_user_func('get_object_vars', $this);

the "trick" is that get_object_vars is being called from the scope of call_user_func and not the scope of the object

no need for reflection, stand-alone functions, closures, etc

Solution 3:[3]

Another (PHP 7.* compatible) way is to cast $this to an array and filter out any binary keys. This is a little less verbose than using Reflection.

return array_filter(
    (array) $this,
    static fn(string $key): bool => strpos($key, "\0") !== 0, ARRAY_FILTER_USE_KEY,
);

Solution 4:[4]

According to this article (written by Vance Lucas), you can create a new call scope inside your "Foo" class definition using an "anonymous" function, and then you can call get_object_vars() from within. This allow you to get only the public properties from inside your class, even if these have been created dynamically later from the outside.

So adapted to your example it would be:

<?php
class Foo {
    private $bar = '123';
    protected $boo = '456';
    public   $beer = 'yum';

   // return an array of public properties 
   public function getPublicVars(){
      $publicVars = create_function('$obj', 'return get_object_vars($obj);');
        return $publicVars($this);
   } 
}

 $foo = new Foo();
 $foo->tricky = 'dynamically added var';

 $result = $foo->getPublicVars();  
 print_r($result);

and the output will be:

Array
(
    [beer] => yum
    [tricky] => dynamically added var
)

There is a second example in the article mentioned above that shows another way to do the same using the so-called "closures" (from php 5.3) but for some reason it doesn't work for me with php v5.4 so the private and protected properties remains included in the resulting array.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 hakre
Solution 2
Solution 3 Doeke Norg
Solution 4 Community