Čamo
Čamo

Reputation: 4163

How to make PHP StdClass reflection

I have a function to log php vaiables to the file. There is a section which handles objects elseif(is_object($var))... and it works well with any application objects. BUT it does not work if the variable is objects of StdClass. I dont understand where is the difference between other objects and StdClass object. Here is the code of the function:

function varLog( $var, $log = 'info', $depth = 2, $round = 0)
{
    $logFile = __DIR__ . '/../log/' . $log . '.log';
    file_put_contents( $logFile, '(' . gettype( $var ) . ') ', FILE_APPEND );

    if( in_array( gettype($var), ['integer', 'double', 'string'] ) )
    {
        file_put_contents( $logFile, $var . PHP_EOL, FILE_APPEND );
    }
    elseif( in_array( gettype($var), ['boolean', 'NULL'] ) )
    {
        $var = is_null( $var ) ? 'NULL' : ($var ? 'TRUE' : 'FALSE');
        file_put_contents( $logFile, $var . PHP_EOL, FILE_APPEND );
    }
    elseif ( is_array( $var ) )
    {
        file_put_contents( $logFile, 'length ' . count($var) . PHP_EOL, FILE_APPEND );

        foreach ( $var as $key => $val )
        {
            file_put_contents( $logFile, str_repeat('    ', $round + 1) . $key . ' => ', FILE_APPEND );
            if ( $round + 1 <= $depth )
            {
                varLog( $val, $log, $depth, $round + 1 );
            }
            else
            {
                file_put_contents( $logFile, '(' . gettype( $val ) . ')' . PHP_EOL, FILE_APPEND );
            }
        }
    }
    elseif ( is_object( $var ) )
    {
        file_put_contents( $logFile, get_class( $var ) . PHP_EOL, FILE_APPEND );
        $props = (new ReflectionClass( $var ))->getProperties();
        foreach ( $props as $prop )
        {
            $prop->setAccessible( true );
            $scoope = $prop->isPrivate() ? '(private)' : ($prop->isProtected() ? '(protected)' : '(public)');
            file_put_contents( $logFile, str_repeat('   ', $round + 1) . $scoope . ' ' . $prop->name . ' => ', FILE_APPEND );
            if ( $round + 1 <= $depth )
            {
                varLog( $prop->getValue( $var ), $log, $depth, $round + 1 );
            }
            else
            {
                file_put_contents( $logFile, '(' . gettype( $prop->getValue( $var ) ) . ')' . PHP_EOL, FILE_APPEND );
            }
        }
    }
}

It seems the line

$props = (new ReflectionClass( $var ))->getProperties();

does not return any props.

Upvotes: 2

Views: 893

Answers (2)

Brad Kent
Brad Kent

Reputation: 5098

FWIW PHP < 7.0 has/had a bug

$obj = (object) array(
    // stdClass with numeric prop names/keys
    'foo',
    'bar',
);
$ref = new ReflectionObject($obj);
var_dump($ref->getProperties(); // empty array

$obj = (object) array(
    'a' => 'foo',
    'b' => 'bar',
);
$ref = new ReflectionObject($obj);
var_dump($ref->getProperties()); // non-empty

Upvotes: 1

Chin Leung
Chin Leung

Reputation: 14921

PHP has ReflectionClass and ReflectionObject. You can use ReflectionObject for StdClass.

$props = (new ReflectionObject(($var))->getProperties();

Otherwise you can use get_object_vars:

$props = get_object_vars($var);

The difference between the two is that ReflectionClass would only return the original properties of the class.

Suppose that you have the following class:

class Test {
    public $foo;
}

Then you create an instance of it and assign a new property:

$instance = new Test;
$instance->bar = 'foo';

Then if you retrieve the properties of the class with ReflectionClass:

(new ReflectionClass($instance))->getProperties();

It does not return the bar property:

[
    ReflectionProperty {#3059
        +name: "foo",
        +class: "Test",
        modifiers: "public",
    },
]

Hence the empty array when you use ReflectionClass with StdClass. Whereas the ReflectionObject would return both:

(new ReflectionObject($instance))->getProperties();

The output is:

[
    ReflectionProperty {#3071
        +name: "foo",
        +class: "Test",
        modifiers: "public",
    },
    ReflectionProperty {#3073
        +name: "bar",
        +class: "Test",
        modifiers: "public",
    },
]

Source: https://gist.github.com/wjaspers/9353164

Upvotes: 3

Related Questions