-
Notifications
You must be signed in to change notification settings - Fork 0
core.reflection
The XP framework offers its own reflection API.
The most common entry point is the lang.XPClass
class.
Instances of it can be retrieved by either using its static forName()
method or by calling the instance method getClass()
on any object.
<?php
$class= XPClass::forName('util.collections.HashTable');
$class= create(new HashTable())->getClass();
?>
Hint: To retrieve an object's class name, you can either use $object->getClass()->getName()` or the shortcut `$object->getClassName()
. The latter is not only shorter but also significantly faster!
With the XPClass
instance in the $class
variable, one has
access to all features of a class:
<?php
$method= $class->getMethod('toString');
?>
The returned lang.reflect.Method
instance offers access
to:
-
Parameters - via
getParameters()
-
Return type - via
getReturnType()
-
Thrown exceptions - via
getExceptionTypes()
-
Annotations - via
getAnnotations()
-
Modifiers - via
getModifiers()
...and provides means to invoke the method:
<?php
with ($class= XPClass::forName('util.log.Logger')); {
$log= $class->getMethod('getInstance')->invoke(NULL); // Static
$str= $class->getMethod('toString')->invoke($log); // Instance
}
?>
<?php
$constructor= $class->getConstructor();
?>
The returned lang.reflect.Constructor
instance offers access to:
-
Parameters - via
getParameters()
-
Thrown exceptions - via
getExceptionTypes()
-
Annotations - via
getAnnotations()
-
Modifiers - via
getModifiers()
...and provides means to invoke it:
<?php
with ($class= XPClass::forName('util.Binford')); {
$binford6100= $class->getConstructor()->invoke(array(6100));
}
?>
<?php
$field= $class->getField('elements');
?>
The returned lang.reflect.Field
instance offers access
to:
-
Type - via
getType()
-
Modifiers - via
getModifiers()
...and provides means to read its value:
<?php
with ($class= XPClass::forName('util.Binford')); {
$power= $class->getField('poweredBy')->get(new Binford(6100));
}
?>
<?php
#[@bean(name= 'contract/history/1.0')]
class HistoryBean extends Object {
}
$name= XPClass::forName('HistoryBean')->getAnnotation('bean', 'name');
?>
See also the Annotations documentation.
Every class resides inside a package. The lang.reflect.Package
class offers methods to reflectively access a package. Instances of it can be
retrieved by Package::forName()
or by calling the getPackage()
on an XPClass
instance.
<?php
$package= Package::forName('util.collections');
$package= create(new HashTable())->getClass()->getPackage();
?>
Packages are primarily used to load classes and resources:
<?php
$package= Package::forName('de.thekid.dialog.scriptlet.state');
$stateName= ucfirst($request->getURL()->getPath());
try {
$state= $package->loadClass($stateName.'State')->newInstance();
} catch (ClassNotFoundException $e) {
throw new HttpScriptletException('File not found', HTTP_NOT_FOUND, $e);
}
?>
The nice thing about this piece of code is that it will not let users
inject arbitrary class names but will throw an lang.IllegalArgumentException
in case
a class outside of the given package.
To retrieve a config.ini
inside the same directory as the class
containing the sourcecode one can use the following:
<?php
$prop= Properties::fromString($this->getClass()
->getPackage()
->getResource('config.ini')
);
?>