Here is a list of missing features or bugs I met while using Reflection API (with PHP Version 5.2.3-1ubuntu6.3) ;
Missing a ReflectionConstant class
It's possible to get information about many things, but constants have been forgotten.
For non-object constants, the only available function I know is
get_defined_constants().
For class constants, the only method I know is
ReflectionClass::getConstants(), which just gives an array of constant names with their values.
So in both cases, there is no way to retrieve the doc comment, the filename or the line where the constant is defined.
Missing methods in ReflectionProperty class
-
getStartLine() is missing
-
getFilename() is also missing, but it's possible to get the information through
getDeclaringClass()->getFilename().
No doc comments for internal php classes or functions
This feature would permit to generate an API documentation of PHP built-in functions and classes, like Sun does to document java with javadoc.
Problem with interfaces' parents
I was unable to retrieve the
direct parents of an interface with the reflection API.
For example :
interface i1{}
interface i2{}
interface i3 extends i1{}
interface i4 extends i1{}
interface i5 extends i4, i2{}
I needed a way to get the direct parents :
for
i1 : nothing
for
i1 : nothing
for
i3 :
i1
for
i4 :
i1
for
i5 :
i4 and
i2
I couldn't deal with the fact that an interface can have several direct parents (multiple inheritance), mixed with the fact that
getInterfaces() returns also the indirect ancestors.
I tried also with
ReflectionClass::isSubclassOf(), but it returns
true for both direct and indirect ancestors.
To solve that problem, I found no other way to parse the file containing the interface definition.
Confusing getParentClass() and getInterfaces()
There is something not logical in
ReflectionClass::getParentClass(), because it doesn't act the same way with class and interface.
- For a class, it returns the direct parent.
- For an interface, it returns nothing.
So two things expressed the same way in the code (the clause
extends) can't be retrieved by the same method.
The parents of an interface can be obtained through
ReflectionClass::getInterfaces() (on this point, documentation is missing in the php manual).
But here is an other incoherence :
- For a class, it returns the implemented interfaces and their ancestors.
- For an interface, it returns the direct parents and the indirect ancestors (grand-parents etc.).
So the same method returns things that are expressed differently in the code (clause
implements for a class, and clause
extends for an interface).
Bug in ReflectionClass::getDocComment() and ReflectionMethod::getDocComment()
If the doc comment doesn't start exactly by
/**, it is not retrieved by the reflection API.
The following code works :
/**
Doc comment for class1
@license GPL
@author Author of this code
*/
class class1{}
//
$class1 = new ReflectionClass('class1');
$doc1 = $class1->getDocComment();
echo "<pre>"; print_r($doc1); echo "</pre>";
The result is :
/**
Doc comment for class1
@license GPL
@author Author of this code
*/
But the following code echoes an empty string :
/******************************
Doc comment for class1
@license GPL
@author Author of this code
******************************/
class class1{}
//
$class1 = new ReflectionClass('class1');
$doc1 = $class1->getDocComment();
echo "<pre>"; print_r($doc1); echo "</pre>";
This happens as soon as the comments starts with more than 2 asterisks.
The same problem occurs with class methods.
Other manifestation of this bug :
/** A constant defined in Class1.php, outside of a class */
define('constant1', 'value of const1');
/******************************
Doc comment for class1
@license GPL
@author Author of this code
******************************/
class class1{}
//
$class1 = new ReflectionClass('class1');
$doc1 = $class1->getDocComment();
echo "<pre>"; print_r($doc1); echo "</pre>";
This echoes :
/** A constant defined in Class1.php, outside of a class */
Fix : this can be patched with a regular expression containing a "not preceeded by" :
'/\/\*{2,}\s*(?P<comment>(?:[^\/]|(?<!\*)\/)*?)\s*\*+\/\s*/s'
This regex strips the comment, removes the leading
/** and trailing
*/, removes also eventual asterisks after
/** or before
*/, but does not remove the decorative asterisks sometimes found at beginning of lines in doc comments.
Declaring instruction
I wanted to retrieve the exact instruction used to declare an element (class, method etc.), and couldn't achieve this with Reflection API. I tried with
getModifiers() and
Reflection::getModifierNames(), but didn't suceed.
This code :
class Class1{
public static function method1(){}
static public function method2(){}
static public static public public function method3(){} // yes, this stange syntax is legal...
}
$class1 = new ReflectionClass('Class1');
$method1 = $class1->getMethod('method1');
$method2 = $class1->getMethod('method2');
$method3 = $class1->getMethod('method3');
echo "<br/>method1 : "; print_r(Reflection::getModifierNames($method1->getModifiers()));
echo "<br/>method2 : "; print_r(Reflection::getModifierNames($method2->getModifiers()));
echo "<br/>method3 : "; print_r(Reflection::getModifierNames($method3->getModifiers()));
echoes :
method1 : Array ( [0] => public [1] => static )
method2 : Array ( [0] => public [1] => static )
method3 : Array ( [0] => public [1] => static )
I didn't find a way to retrieve the declaring instruction as it is in the code.
But maybe the need to retrieve the exact declaring instruction of a php element is out of the scope of php reflection API.