When your class extends a parent class you maybe want the name
of them. Using getParentClass() is maybe a bit confusing. When
you want the name as string try the following.
<?php
$class = new ReflectionClass('whatever');
$parent = (array) $class->getParentClass();
if(array_key_exists('name', $parent))
{
# name of the parent class
$parent = parent['name'];
}
else
{
# no parent class avaible
$parent = false;
}
?>
When you turn getParentClass() to an array it will result either
array(0 => false) when no parent class exist or
array('name' => 'name of the parent class'). Tested on PHP 5.2.4
Réflexion
Sommaire
- Introduction
- L'interface de réflection
- La classe ReflectionException
- La classe ReflectionFunction
- La classe ReflectionParameter
- La classe ReflectionClass
- La classe ReflectionObject
- La classe ReflectionMethod
- La classe ReflectionProperty
- La classe ReflectionExtension
- Étendre les classes de réflection
Introduction
PHP 5 introduit API de réflexion complète qui permet de faire du reverse-engineering sur les classes, les interfaces, les fonctions et les méthodes tout comme les extensions. L'API de réflexion permet également d'obtenir les commentaires de la documentation pour les fonctions, les classes et les méthodes.
L'API de réflexion est une extension orientée objet du Moteur Zend, constituée des classes suivantes :
Exemple #1 API de réflexion
<?php
class Reflection { }
interface Reflector { }
class ReflectionException extends Exception { }
class ReflectionFunction extends ReflectionFunctionAbstract implements Reflector { }
class ReflectionParameter implements Reflector { }
class ReflectionMethod extends ReflectionFunctionAbstract implements Reflector { }
class ReflectionClass implements Reflector { }
class ReflectionObject extends ReflectionClass { }
class ReflectionProperty implements Reflector { }
class ReflectionExtension implements Reflector { }
?>
Note: Pour plus de détails sur ces classes, lisez les chapitres suivants.
Si nous exécutons le code de l'exemple ci-dessous :
Exemple #2 Utilisation basique de l'API de réflexion
<?php
Reflection::export(new ReflectionClass('Exception'));
?>
L'exemple ci-dessus va afficher :
Class [ <internal> class Exception ] { - Constants [0] { } - Static properties [0] { } - Static methods [0] { } - Properties [6] { Property [ <default> protected $message ] Property [ <default> private $string ] Property [ <default> protected $code ] Property [ <default> protected $file ] Property [ <default> protected $line ] Property [ <default> private $trace ] } - Methods [9] { Method [ <internal> final private method __clone ] { } Method [ <internal, ctor> public method __construct ] { - Parameters [2] { Parameter #0 [ <optional> $message ] Parameter #1 [ <optional> $code ] } } Method [ <internal> final public method getMessage ] { } Method [ <internal> final public method getCode ] { } Method [ <internal> final public method getFile ] { } Method [ <internal> final public method getLine ] { } Method [ <internal> final public method getTrace ] { } Method [ <internal> final public method getTraceAsString ] { } Method [ <internal> public method __toString ] { } } }
Reflector
Reflector est une interface implémentée par toutes les classes exportables de réflection.
<?php
interface Reflector
{
public string __toString()
public static string export()
}
?>
ReflectionException
ReflectionException étend le standard Exception et est lancé par l'API Reflection. Aucune méthode spécifique ni de propriété ne sont introduites.
ReflectionFunction
La classe ReflectionFunction vous permet de faire du reverse-engineering sur les fonctions.
Exemple #3 La classe ReflectionFunction
<?php
class ReflectionFunction extends ReflectionFunctionAbstract implements Reflector
{
final private __clone()
public void __construct(string name)
public string __toString()
public static string export(string name, bool return)
public string getName()
public bool isInternal()
public bool isDisabled()
public bool isUserDefined()
public string getFileName()
public int getStartLine()
public int getEndLine()
public string getDocComment()
public array getStaticVariables()
public mixed invoke([mixed args [, ...]])
public mixed invokeArgs(array args)
public bool returnsReference()
public ReflectionParameter[] getParameters()
public int getNumberOfParameters()
public int getNumberOfRequiredParameters()
}
?>
La classe parent ReflectionFunctionAbstract a les mêmes méthodes, exceptée invoke(), invokeArgs(), export() et isDisabled().
Note: getNumberOfParameters() et getNumberOfRequiredParameters() ont été ajoutés en PHP 5.0.3, tandis que invokeArgs() a été ajouté en PHP 5.1.0.
Pour connaître le fonctionnement d'une fonction, vous devez tout d'abord créer une instance de la classe ReflectionFunction. Ainsi, vous pouvez appeler n'importe quelle méthode de cette instance.
Exemple #4 Utilisation de la classe ReflectionFunction
<?php
/**
* Un simple compteur
*
* @return int
*/
function counter()
{
static $c = 0;
return $c++;
}
// Création d'une instance de la classe ReflectionFunction
$func = new ReflectionFunction('counter');
// Affichage d'informations basiques
printf(
"===> The %s function '%s'\n".
" declared in %s\n".
" lines %d to %d\n",
$func->isInternal() ? 'internal' : 'user-defined',
$func->getName(),
$func->getFileName(),
$func->getStartLine(),
$func->getEndline()
);
// Affichage du commentaire de la documentation
printf("---> Documentation:\n %s\n", var_export($func->getDocComment(), 1));
// Affichage des variables statiques si elles existent
if ($statics = $func->getStaticVariables())
{
printf("---> Variables statiques : %s\n", var_export($statics, 1));
}
// Appel de la fonction
printf("---> Invocation des résultats dans : ");
var_dump($func->invoke());
// vous pouvez préférer utiliser la méthode export()
echo "\nRésultat de ReflectionFunction::export() :\n";
echo ReflectionFunction::export('counter');
?>
Note: La méthode invoke() accepte un nombre variable d'arguments, tout comme la fonction call_user_func().
ReflectionParameter
La classe ReflectionParameter récupère les informations concernant les paramètres des fonctions ou des méthodes.
Exemple #5 La classe ReflectionParameter
<?php
class ReflectionParameter implements Reflector
{
final private __clone()
public object __construct(string function, string parameter)
public string __toString()
public static string export(mixed function, mixed parameter, bool return)
public string getName()
public bool isPassedByReference()
public ReflectionClass getDeclaringClass()
public ReflectionClass getClass()
public bool isArray()
public bool allowsNull()
public bool isPassedByReference()
public bool isOptional()
public bool isDefaultValueAvailable()
public mixed getDefaultValue()
public int getPosition()
}
?>
Note: getDefaultValue(), isDefaultValueAvailable() et isOptional() ont été ajoutés en PHP 5.0.3, tandis que isArray() a été ajoutée en PHP 5.1.0. getDeclaringFunction() et getPosition() ont été ajoutés en PHP 5.2.3.
Pour connaître le fonctionnement des paramètres d'une fonction, vous devez tout d'abord créer une instance de la classe ReflectionFunction ou ReflectionMethod et, ainsi, utiliser leurs méthodes getparameters() pour récupérer un tableau de paramètres.
Exemple #6 Utilisation de la classe ReflectionParameter
<?php
function foo($a, $b, $c) { }
function bar(Exception $a, &$b, $c) { }
function baz(ReflectionFunction $a, $b = 1, $c = null) { }
function abc() { }
// Création d'une instance de la classe ReflectionFunction avec le
// paramètre fourni en ligne de commande.
$reflect = new ReflectionFunction($argv[1]);
echo $reflect;
foreach ($reflect->getParameters() as $i => $param) {
printf(
"-- Paramètre #%d : %s {\n".
" Classe : %s\n".
" Autorise NULL : %s\n".
" Passé par référence : %s\n".
" Est optionnel ?: %s\n".
"}\n",
$i, // $param->getPosition() peut être utilisé depuis PHP 5.2.3
$param->getName(),
var_export($param->getClass(), 1),
var_export($param->allowsNull(), 1),
var_export($param->isPassedByReference(), 1),
$param->isOptional() ? 'oui' : 'non'
);
}
?>
ReflectionClass
La classe ReflectionClass vous permet de faire du reverse-engineering sur des classes et des interfaces.
Exemple #7 La classe ReflectionClass
<?php
class ReflectionClass implements Reflector
{
final private __clone()
public object __construct(string name)
public string __toString()
public static string export(mixed class, bool return)
public string getName()
public bool isInternal()
public bool isUserDefined()
public bool isInstantiable()
public bool hasConstant(string name)
public bool hasMethod(string name)
public bool hasProperty(string name)
public string getFileName()
public int getStartLine()
public int getEndLine()
public string getDocComment()
public ReflectionMethod getConstructor()
public ReflectionMethod getMethod(string name)
public ReflectionMethod[] getMethods()
public ReflectionProperty getProperty(string name)
public ReflectionProperty[] getProperties()
public array getConstants()
public mixed getConstant(string name)
public ReflectionClass[] getInterfaces()
public bool isInterface()
public bool isAbstract()
public bool isFinal()
public int getModifiers()
public bool isInstance(stdclass object)
public stdclass newInstance(mixed args)
public stdclass newInstanceArgs(array args)
public ReflectionClass getParentClass()
public bool isSubclassOf(ReflectionClass class)
public array getStaticProperties()
public mixed getStaticPropertyValue(string name [, mixed default])
public void setStaticPropertyValue(string name, mixed value)
public array getDefaultProperties()
public bool isIterateable()
public bool implementsInterface(string name)
public ReflectionExtension getExtension()
public string getExtensionName()
}
?>
Note: hasConstant(), hasMethod(), hasProperty(), getStaticPropertyValue() et setStaticPropertyValue() ont été ajoutées en PHP 5.1.0, tandis que newInstanceArgs() a été ajoutée dans PHP 5.1.3.
Pour connaître le fonctionnement d'une classe, vous devez d'abord créer une instance de la classe ReflectionClass. Vous pourrez donc appeler n'importe quelle méthode sur cette instance.
Exemple #8 Utilisation de la classe ReflectionClass
<?php
interface Linearisable
{
// ...
}
class Object
{
// ...
}
/**
* Une classe compteur
*
*/
class Compteur extends Object implements Linearisable
{
const START = 0;
private static $c = Compteur::START;
/**
* Invocation du compteur
*
* @access public
* @return int
*/
public function count()
{
return self::$c++;
}
}
// Création d'une instance de la classe ReflectionClass
$class = new ReflectionClass('Compteur');
// Affichage d'informations basiques
printf(
"===> La %s%s%s %s '%s' [extension de %s]\n".
" déclarée dans %s\n".
" lignes %d à %d\n".
" a le modificateur %d [%s]\n",
$class->isInternal() ? 'internal' : 'user-defined',
$class->isAbstract() ? ' abstract' : '',
$class->isFinal() ? ' final' : '',
$class->isInterface() ? 'interface' : 'class',
$class->getName(),
var_export($class->getParentClass(), 1),
$class->getFileName(),
$class->getStartLine(),
$class->getEndline(),
$class->getModifiers(),
implode(' ', Reflection::getModifierNames($class->getModifiers()))
);
// Affichage du commentaire de la documentation
printf("---> Documentation:\n %s\n", var_export($class->getDocComment(), 1));
// Affichage de l'interface qui implémente cette classe
printf("---> Implémenté :\n %s\n", var_export($class->getInterfaces(), 1));
// Affichage des constantes de la classe
printf("---> Constantes : %s\n", var_export($class->getConstants(), 1));
// Affichage des propriétés de la classe
printf("---> Properties: %s\n", var_export($class->getProperties(), 1));
// Affichage des méthodes de la classe
printf("---> Méthodes : %s\n", var_export($class->getMethods(), 1));
// Si cette classe est instanciable, création d'une instance
if ($class->isInstantiable()) {
$counter = $class->newInstance();
echo '---> $counter est uneinstance ? ';
echo $class->isInstance($counter) ? 'oui' : 'non';
echo "\n---> Le nouvel objet Object() est une instance ? ";
echo $class->isInstance(new Object()) ? 'oui' : 'non';
}
?>
Note: La méthode newinstance() accepte un nombre variable d'arguments, tout comme la fonction call_user_func().
Note: $class = new ReflectionClass('Foo'); $class->isInstance($arg) est équivalent à $arg instanceof Foo ou is_a($arg, 'Foo').
ReflectionObject
La classe ReflectionObject vous permet de retrouver les objets.
<?php
class ReflectionObject extends ReflectionClass
{
final private __clone()
public object __construct(mixed object)
public string __toString()
public static string export(mixed object, bool return)
}
?>
ReflectionMethod
La classe ReflectionMethod vous permet de faire du reverse-engineering sur les méthodes des classes.
Exemple #9 La classe ReflectionMethod
<?php
class ReflectionMethod extends ReflectionFunctionAbstract implements Reflector
{
public __construct(mixed class, string name)
public string __toString()
public static string export(mixed class, string name, bool return)
public mixed invoke(stdclass object [, mixed args [, ...]])
public mixed invokeArgs(stdclass object, array args)
public bool isFinal()
public bool isAbstract()
public bool isPublic()
public bool isPrivate()
public bool isProtected()
public bool isStatic()
public bool isConstructor()
public bool isDestructor()
public int getModifiers()
public ReflectionClass getDeclaringClass()
// Inherited from ReflectionFunctionAbstract
final private __clone()
public string getName()
public bool isInternal()
public bool isUserDefined()
public string getFileName()
public int getStartLine()
public int getEndLine()
public string getDocComment()
public array getStaticVariables()
public bool returnsReference()
public ReflectionParameter[] getParameters()
public int getNumberOfParameters()
public int getNumberOfRequiredParameters()
}
?>
Pour connaître le fonctionnement d'une méthode, vous devez d'abord créer une instance de la classe ReflectionMethod. Vous pourrez ainsi appeler n'importe quelle méthode de cette instance.
Exemple #10 Utilisation de la classe ReflectionMethod
<?php
class Compteur
{
private static $c = 0;
/**
* Incrémentation d'un compteur
*
* @final
* @static
* @access public
* @return int
*/
final public static function increment()
{
return self::$c;
}
}
// Création d'une instance de la classe ReflectionMethod
$method = new ReflectionMethod('Compteur', 'increment');
// Affichage d'informations basiques
printf(
"===> La méthode %s%s%s%s%s%s%s '%s' (qui est %s)\n".
" déclaré dans %s\n".
" lignes %d à %d\n".
" a les modificateurs %d[%s]\n",
$method->isInternal() ? 'internal' : 'user-defined',
$method->isAbstract() ? ' abstract' : '',
$method->isFinal() ? ' final' : '',
$method->isPublic() ? ' public' : '',
$method->isPrivate() ? ' private' : '',
$method->isProtected() ? ' protected' : '',
$method->isStatic() ? ' static' : '',
$method->getName(),
$method->isConstructor() ? 'the constructor' : 'a regular method',
$method->getFileName(),
$method->getStartLine(),
$method->getEndline(),
$method->getModifiers(),
implode(' ', Reflection::getModifierNames($method->getModifiers()))
);
// Affichage du commentaire de la documentation
printf("---> Documentation:\n %s\n", var_export($method->getDocComment(), 1));
// Affichage des variables statiques si elles existent
if ($statics= $method->getStaticVariables()) {
printf("---> Variales statiques : %s\n", var_export($statics, 1));
}
// Invocation de la méthode
printf("---> Résultat de l'invocation dans : ");
var_dump($method->invoke(NULL));
?>
Note: Invoquer des méthodes privées, protégées ou abstraites provoquera une exception jetée par la méthode invoke().
Note: Pour les méthodes statiques comme vu précédemment, vous devez passer NULL comme premier argument à la fonction invoke(). Pour les méthodes non-statiques, passez une instance de la classe.
ReflectionProperty
La classe ReflectionProperty vous permet de faire du reverse-engineering sur les propriétés des classes.
Exemple #11 La classe ReflectionProperty
<?php
class ReflectionProperty implements Reflector
{
final private __clone()
public __construct(mixed class, string name)
public string __toString()
public static string export(mixed class, string name, bool return)
public string getName()
public bool isPublic()
public bool isPrivate()
public bool isProtected()
public bool isStatic()
public bool isDefault()
public int getModifiers()
public mixed getValue(stdclass object)
public void setValue(stdclass object, mixed value)
public ReflectionClass getDeclaringClass()
public string getDocComment()
}
?>
Note: getDocComment() a été ajouté en PHP 5.1.0.
Pour connaître le fonctionnement d'une propriété, vous devez d'abord créer une instance de la classe ReflectionProperty. Vous pourrez ainsi appeler n'importe quelle méthode de cette instance.
Exemple #12 Utilisation de la classe ReflectionProperty
<?php
class Chaine
{
public $length = 5;
}
// Création d'une instance de la classe ReflectionProperty
$prop = new ReflectionProperty('Chaine', 'length');
// Affichage d'informations basiques
printf(
"===> Les propriétés %s%s%s%s '%s' (qui a %s)\n".
" a les modificateurs %s\n",
$prop->isPublic() ? ' public' : '',
$prop->isPrivate() ? ' private' : '',
$prop->isProtected() ? ' protected' : '',
$prop->isStatic() ? ' static' : '',
$prop->getName(),
$prop->isDefault() ? 'déclaré au moment de la compilation' : 'créé au moment de l\'exécution',
var_export(Reflection::getModifierNames($prop->getModifiers()), 1)
);
// Création d'une instance de Chaine
$obj= new Chaine();
// Récupération de la valeur courante
printf("---> La veleur est : ");
var_dump($prop->getValue($obj));
// Modification de la valeur
$prop->setValue($obj, 10);
printf("---> Définition de la valeur à 10, la nouvelle valeur est : ");
var_dump($prop->getValue($obj));
// Affichage de l'objet
var_dump($obj);
?>
Note: Essayer de récupérer ou de définir les valeurs des propriétés d'une classe privée ou protégée produira une exception.
ReflectionExtension
La classe ReflectionExtension vous permet de faire du reverse-engineering sur les extensions. Vous pouvez connaître toutes les extensions chargées à l'exécution en utilisation la fonction get_loaded_extensions().
Exemple #13 La classe ReflectionExtension
<?php
class ReflectionExtension implements Reflector
{
final private __clone()
public __construct(string name)
public string __toString()
public static string export(string name, bool return)
public string getName()
public string getVersion()
public ReflectionFunction[] getFunctions()
public array getConstants()
public array getINIEntries()
public ReflectionClass[] getClasses()
public array getClassNames()
public string info()
}
?>
Pour connaître le fonctionnement d'une extension, vous devez d'abord créer une instance de la classe ReflectionExtension. Vous pourrez ainsi appeler n'importe quelle méthode sur cette instance.
Exemple #14 Utilisation de la classe ReflectionExtension
<?php
// Création d'une instance de la classe ReflectionProperty
$ext = new ReflectionExtension('standard');
// Affichage d'informations basiques
printf(
"Nom : %s\n".
"Version : %s\n".
"Fonctions : [%d] %s\n".
"Entrées INI : [%d] %s\n" .
"Classes : [%d] %s\n",
$ext->getName(),
$ext->getVersion() ? $ext->getVersion() : 'NO_VERSION',
sizeof($ext->getFunctions()),
var_export($ext->getFunctions(), 1),
sizeof($ext->getConstants()),
var_export($ext->getConstants(), 1),
sizeof($ext->getINIEntries()),
var_export($ext->getINIEntries(), 1),
sizeof($ext->getClassNames()),
var_export($ext->getClassNames(), 1)
);
?>
Extension des classes de réflexion
Dans le cas où vous voudriez créer des versions spéciales des classes embarquées (par exemple pour créer du HTML colorisé lorsqu'il est exporté, pour avoir un accès facile aux variables des membres au lieu des méthodes ou pour avoir des méthodes utiles), vous devez étendre la classe.
Exemple #15 Extension des classes embarquées
<?php
/**
* Ma classe Reflection_Method
*
*/
class My_Reflection_Method extends ReflectionMethod
{
public $visibility = array();
public function __construct($o, $m)
{
parent::__construct($o, $m);
$this->visibility = Reflection::getModifierNames($this->getModifiers());
}
}
/**
* Démo classe #1
*
*/
class T {
protected function x() {}
}
/**
* Démo classe #2
*
*/
class U extends T {
function x() {}
}
// Affichage des informations
var_dump(new My_Reflection_Method('U', 'x'));
?>
Note: Attention : si vous écrasez le constructeur, n'oubliez pas d'appeler le constructeur parent avant d'insérer le moindre code. Sinon, votre code produira l'erreur suivante : Fatal error: Internal error: Failed to retrieve the reflection object
Réflexion
20-Jun-2008 12:47
11-May-2008 09:44
The note about the signature of the ReflectionParameter constructor is actually incomplete, at least in 5.2.5: it is possible to use an integer for the second parameter, and the constructor will use it to return the n-th parameter.
This allows you to obtain proper ReflectionParameter objects even when documenting code from extensions which (strangely enough) define several parameters with the same name. The string-based constructor always returns the first parameter with the matching name, whereas the integer-based constructor correctly returns the n-th parameter.
So, in short, this works:
<?php
// supposing the extension defined something like:
// Some_Class::someMethod($a, $x, $y, $x, $y)
$p = new ReflectionParameter(array('Some_Class', 'someMethod'), 4);
// returns the last parameter, whereas
$p = new ReflectionParameter(array('Some_Class', 'someMethod'), 'y');
// always returns the first $y at position 2
?>
08-Apr-2008 11:32
I think there are still some limitations in the reflection abilities:
* ReflectionClass :: getConstants() returns an associative array with the constants and their values inside. I don't understand, why they don't use an object there, too (e.g. ReflectionConstant). The final effect is, that you aren't able to read out the DocComment of constants.
* There is no nice way to access the default values of properties. You can workaround a bit with get_class_vars(), but this just returns the values of public properties. No way to access protected or even private properties.
* PHP 5 has a nice feature called type hinting. This is completely omitted. You may ask, if a certain parameter is an array, but you won't get the denoted type hint.
Maybe this is, or will be extended. I hope so.
hth,
Niels
08-Apr-2008 12:34
PHP 5.3 will receive Java's setAccessible() functionality for accessing protected/privates.
17-Feb-2008 03:41
I encountered a weird problem with ReflectionFunction, described in ticket 44139 of PHP Bugs.
If for some reason you need to call with invoke, or invokeArgs, a function like array_unshift (that accepts internally the array by reference) you could use this code to avoid the generated warning or fatal error.
<?php
function unshift(){
$ref = new ReflectionFunction('array_unshift');
$arguments = func_get_args();
return $ref->invokeArgs(array_merge(array(&$this->arr), $arguments));
}
?>
I don't know about performances (you can create an array manually too, starting from array(&$this->something) and adding arguments). However, it seems to work correctly without problems, at least until the send by reference will be usable with one single value ...
31-Jan-2008 11:47
Like Will Mason said for the ReflectionMethod's constants, there is filter constants for ReflectionProperty too:
ReflectionProperty::IS_STATIC
ReflectionProperty::IS_PUBLIC
ReflectionProperty::IS_PROTECTED
ReflectionProperty::IS_PRIVATE
that can be used in the ReflectionClass' method getProperties:
$class=new ReflectionClass("Foo");
$class->getProperties(
ReflectionProperty::IS_STATIC |
ReflectionProperty::IS_PUBLIC );
this obtains the publics (static or not) and the statics (public or not): this exlude the non static private properties.
04-Dec-2007 02:16
If you are getting
Fatal error: Trying to clone an uncloneable object of class ReflectionClass in …
Ensure that this is set.
zend.ze1_compatibility_mode=Off in php.ini
Thanks to anil who posted this on www.tecpages.com
03-Aug-2007 10:29
If you are looking for the long $filters for ReflectionClass::getMethods(), here they are. They took me a long time to find. Found nothing in the docs, nor google. But of course, Reflection itself was the final solution, in the form of ReflectionExtension::export("Reflection").
<?php
//The missing long $filter values!!!
ReflectionMethod::IS_STATIC;
ReflectionMethod::IS_PUBLIC;
ReflectionMethod::IS_PROTECTED;
ReflectionMethod::IS_PRIVATE;
ReflectionMethod::IS_ABSTRACT;
ReflectionMethod::IS_FINAL;
//Use them like this
$R = new ReflectionClass("MyClass");
//print all public methods
foreach ($R->getMethods(ReflectionMethod::IS_PUBLIC) as $m)
echo $m->__toString();
?>
25-Jul-2007 02:53
Signature of constructor of ReflectionParameter correctly is:
public function __construct(array/string $function, string $name);
where $function is either a name of a global function, or a class/method name pair.
18-Jul-2007 05:58
I found these limitations using class ReflectionParameter from ReflectionFunction with INTERNAL FUNCTIONS (eg print_r, str_replace, ... ) :
1. parameter names don't match with manual: (try example 19.35 with arg "call_user_func" )
2. some functions (eg PCRE function, preg_match etc) have EMPTY parameter names
3. calling getDefaultValue on Parameters will result in Exception "Cannot determine default value for internal functions"
05-Sep-2006 11:19
If you need to try to do something with the phpdoc or like the java notations in php4, you can create your own
'reflection functions'. This is a litle example of that.
<?php
/**
* Comment used to start a phpdoc
* @author Thiago Mata
* @package notations
*/
define( 'START_DOC' , '/**' );
/**
* Comment used to end a phpdoc
* @author Thiago Mata
* @package notations
*/
define( 'END_DOC' , '*/' );
/**
* Comment used to indicate a tag of phpdoc
* @author Thiago Mata
* @package notations
*/
define( 'TAG_DOC' , '@' );
/**
* This is a function maded in PHP4 to get the notations from some php file.
* Can use comments with many lines
*
* @author Thiago Mata
* @date 05/09/2006
* @package notations
* @param string $strFile
* @copyright open source
* @example <code> $arrNotations = getFileNotations( 'somefile.php' ); </code>
*/
function getFileNotations( $strFile )
{
$strText = file_get_contents( $strFile );
$arrText = explode( "\n" , $strText );
$arrNotations = array();
for ( $intCount = 0 ; $intCount < count( $arrText ) ; ++$intCount )
{
$strLine = $arrText[ $intCount ];
// inside the phpdoc //
if ( strpos( trim( $strLine ) , START_DOC ) === 0 )
{
++$intCount;
$strLine = $arrText[ $intCount ];
$arrNotation = array();
// while the phpdoc is not finished //
while ( ( strpos( trim( $strLine ) , END_DOC ) !== 0 ) and ( $intCount < count( $arrText ) ) )
{
// removing the tag doc from the line //
$strLine = substr( $strLine , strpos( $strLine , TAG_DOC ) );
// get the name of the tag //
$strName = substr( $strLine , 0 , strpos( $strLine , ' ' ) );
// get the value of the tag //
$strLine = substr( $strLine , strpos( $strLine , ' ' ) + 1 );
if ( strpos( trim( $strLine ) , '*' ) === 0 )
{
$strLine = substr( $strLine , strpos( $strLine , '*' ) + 1 );
}
$strLine = trim( $strLine );
if ( ! isset( $arrNotation[ $strName ] ) )
{
$arrNotation[ $strName ] = '';
}
else
{
if ( $strLine != '' )
{
$arrNotation[ $strName ] .= "\n";
}
}
$arrNotation[ $strName ] .= trim( $strLine );
++$intCount;
$strLine = $arrText[ $intCount ];
}
if ( $intCount < count( $arrText ) )
{
do
{
++$intCount;
$strLine = $arrText[ $intCount ];
}
while ( $strLine == '' );
// adding the notation to the next command line //
$arrNotations[ trim( $arrText[ $intCount ] ) ] = $arrNotation;
$intCount--;
}
}
}
return( $arrNotations );
}
print( '<pre>' . "\n" );
var_export( getFileNotations( __FILE__ ) );
print( '</pre>' . "\n" );
?>
<!-- OUTPUT
array (
'define( \'START_DOC\' , \'/**\' );' =>
array (
'' => 'Comment used to start a phpdoc',
'@author' => 'Thiago Mata',
'@package' => 'no