parser-reflection icon indicating copy to clipboard operation
parser-reflection copied to clipboard

ReflectionClass::getParentClass with preloaded classes

Open MaximilianKresse opened this issue 8 years ago • 1 comments

I discovered a strange behaviour regardings classes which are already loaded / declared.

<?php
// A.php
class A
{
    protected $test = 'Hello World';
}
<?php
// B.php
class B extends A
{
}
<?php
// index.php
require_once('vendor/autoload.php');

$locator = new \Go\ParserReflection\Locator\CallableLocator(function($className) {
    if (strpos($className, '\\') !== 0) {
        $className = '\\' . $className;
    }

    if ($className === '\A') {
        return __DIR__ . '/A.php';
    }
    
    if ($className === '\B') {
        return __DIR__ . '/B.php';
    }
    
    return false;
});
\Go\ParserReflection\ReflectionEngine::init($locator);

//require_once('A.php');

$parsedFile = new \Go\ParserReflection\ReflectionFile('B.php');
$fileNameSpaces = $parsedFile->getFileNamespaces();
foreach ($fileNameSpaces as $namespace) {
    $classes = $namespace->getClasses();
    foreach ($classes as $class) {
        foreach ($class->getProperties() as $property) {
            echo "Found class property: ", $class->getName(), '->', $property->getName(), ' default Value: ', $property->getValue(), PHP_EOL;
        }
    }
}

When you run this code the output is:

Found class property: B->test default Value: Hello World

But if I remove the comment before "require_once('A.php');" to load class A the output is:

Fatal error: Uncaught ReflectionException: Cannot access non-public member A::test

This problem only occurs when calling "getParentClass" (getProperties calls internally getParentClass). "getParentClass" returns a \ReflectionClass instead of a "\Go\ParserReflection\ReflectionClass".

The problem seems to be here: https://github.com/goaop/parser-reflection/blob/master/src/Traits/ReflectionClassLikeTrait.php#L445

It could be fixed with:

if (class_exists($extendsName, false)) {
    $parentClass = new parent($extendsName);
    if ($parentClass->isUserDefined()) {
        $parentClass = new static($extendsName);
    }
} else {
    $parentClass = new static($extendsName);
}

What do you think about this?

MaximilianKresse avatar Jun 12 '17 11:06 MaximilianKresse

This problem only occurs when calling "getParentClass" (getProperties calls internally getParentClass). "getParentClass" returns a \ReflectionClass instead of a "\Go\ParserReflection\ReflectionClass".

This is system-wide behavior, since it also manifests itself in getMethods method as I've reported before in #16.

aik099 avatar Aug 22 '17 06:08 aik099