Skip to content
This repository was archived by the owner on Jan 16, 2019. It is now read-only.

Extendend reflection

Frank Kleine edited this page Feb 28, 2015 · 6 revisions

Deprecated since release 5.3.0, use PHP's native reflection classes instead

Extended Reflection

The Extended Reflection API provided by Stubbles is a layer on top of the default PHP reflection API. For nearly every existing reflection class of PHP an appropriate class exists in Stubbles:

namespace stubbles\lang\reflect;
class ReflectionFunction extends \ReflectionFunction { }
class ReflectionParameter extends \ReflectionParameter { }
class ReflectionMethod extends \ReflectionMethod { }
class ReflectionClass extends \ReflectionClass { }
class ReflectionObject extends \ReflectionObject { }
class ReflectionPackage { }
class ReflectionProperty extends \ReflectionProperty { }
class ReflectionExtension extends \ReflectionExtension { }

The only class that has no complement in Stubbles is the ReflectionException class. All classes of the extended reflection API throw this exception in case something goes wrong, you don't need to catch another exception.

The only class without a counterpart is the stubbles\lang\reflect\ReflectionPackage class.

To stay within the extended reflection layer all methods that return another class of the PHP reflection API have been overloaded to return the appropriate Stubbles reflection class. E.g., if you call the stubbles\lang\reflect\ReflectionClass::getMethod() the result will be an instance of stubbles\lang\reflect\ReflectionMethod. That means if you start reflection with the Stubbles reflection API you will always stay within theses classes, if you start reflection with the default PHP implementation you will stay within the PHP classes.

Any other methods of the default PHP reflection classes remain as they are.

Reflection via stubbles\lang\reflect()

Available since release 3.1.0

To provide more convenience a function stubbles\lang\reflect() is provided. It allows to reflect classes, objects and methods:

$refClass  = stubbles\lang\reflect('some\interesting\UserDefinedClass'); // creates instance of stubbles\lang\reflect\ReflectionClass
$refObject = stubbles\lang\reflect($someObjectInstance); // creates instance of stubbles\lang\reflect\ReflectionObject
$refMethod = stubbles\lang\reflect('some\interesting\UserDefinedClass', 'aMethod'); // creates instance of stubbles\lang\reflect\ReflectionMethod
$refMethod = stubbles\lang\reflect($someObjectInstance, 'aMethod'); // same as line before

Since release 4.0.0, it also allows to reflect functions:

$refFunction = stubbles\lang\reflect('someFunction'); // creates instance of stubbles\lang\reflect\ReflectionFunction

Additionally, one can use stubbles\lang\reflectConstructor() to access the constructor of a class:

$refMethod =  stubbles\lang\reflectConstructor('some\interesting\UserDefinedClass'); // same as stubbles\lang\reflect('some\interesting\UserDefinedClass', '__construct');
$refMethod =  stubbles\lang\reflectConstructor($someObjectInstance); // same as stubbles\lang\reflect('some\interesting\UserDefinedClass', '__construct');

Getting informations about annotations

The extended reflection API offers you something which the default PHP implementation does not have and probably will never have: annotations (see Java annotations for more details how to use this in a programming language). Additional methods are provided by classes implementing the stubbles\lang\reflect\annotation\Annotatable interface:

hasAnnotation($annotationName);

Returns true if the function, method, class or property has an annotation defined with the given name.

annotation($annotationName); // since 5.0.0
getAnnotation($annotationName); // deprecated since 5.0.0

Return an instance of the annotation (if it does not exist or something goes wrong while creating the instance a ReflectionException is thrown). As the same annotation can be applied several times, both methods will just return the first one.

Available since release 5.0.0

annotations();

Returns an instance of stubbles\lang\reflect\annotation\Annotations which allows access to all annotations of the annotated element:

contain($type)

Checks if such an annotation is present.

of($type)

Returns a list of all annotations of given type. If no such annotation is present the returned list is empty.

all()

Returns all annotations as list.

The interface is implemented by stubbles\lang\reflect\ReflectionFunction, stubbles\lang\reflect\ReflectionMethod, stubbles\lang\reflect\ReflectionClass, stubbles\lang\reflect\ReflectionObject, stubbles\lang\reflect\ReflectionParameter and stubbles\lang\reflect\ReflectionProperty

Read more about annotations.

Getting the return type of a method or a function

Both stubbles\lang\reflect\ReflectionMethod and stubbles\lang\reflect\ReflectionFunction offer a method getReturnType() which is capable of returning the return type of a method or function. If the return type is a class the return value is an instance of stubbles\reflection\ReflectionClass, if it is a scalar type or an array the return value is an instance of stubbles\reflection\ReflectionPrimitive and if the method does not have a return value this method returns null.

Please be aware that this is guessing from the doc block with which the method or function is documented. If the doc block is missing or incorrect the return value of this method may be wrong. This is due to missing type hints for return values in PHP itself.

Getting methods or properties of a class by a matcher

Sometimes you find yourself in situations writing code such as

$refClass = new stubbles\lang\reflect\ReflectionClass('example\MyClass');
foreach ($refClass->getMethods() as $refMethod) {
        if ($refMethod->isPublic() === false) {
        continue;
    }

    if ($refMethod->isStatic() === true) {
        continue;
    }

    // real action here
}

To limit the amount of such if-clauses both classes for reflecting classes, stubbles\lang\reflect\ReflectionClass and stubbles\lang\reflect\ReflectionObject offer the getMethodsByMatcher() and getPropertiesByMatcher() methods. The code from above can be rewritten using a stubbles\lang\reflect\matcher\MethodMatcher implementation:

$refClass = new stubbles\lang\reflect\ReflectionClass('example\MyClass');
foreach ($refClass->getMethodsByMatcher(new PublicNonStaticMethodMatcher()) as $refMethod) {
    // real action here
}

For properties, the stubbles\lang\reflect\matcher\PropertyMatcher provides a similar possibility.

Clone this wiki locally