PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Контроль типа> <Сравнение объектов
Last updated: Fri, 25 Jul 2008

view this page in

Reflection

Введение

В PHP 5 имеется полный набор Reflection API, который предоставляет возможность проводить реверс-инжиниринг классов, интерфейсов, функций, методов, а также расширений. В дополнение к этому, Reflection API предоставляет средства для извлечения комментариев для функций, классов и методов.

Reflection API - это объектно-ориентированное расширение для Zend Engine, состоящее из следующих классов:

<?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 { }
?>

Замечание: Более подробно эти классы рассматриваются в следующих главах.

Пример #1 Простой пример использования Reflection API

<?php
Reflection
::export(new ReflectionClass('Exception'));
?>

Результат выполнения данного примера:

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 - это интерфейс, который реализуется всеми экспортируемыми классами Reflection.

<?php
interface Reflector
{
    public 
string __toString()
    public static 
string export()
}
?>

ReflectionException

ReflectionException наследует стандартный класс Exception и выбрасывается Reflection API, он не реализует никаких специальных методов или свойств.

ReflectionFunction

Класс ReflectionFunction позволяет проводить реверс-инжиниринг функций.

<?php
class ReflectionFunction extends ReflectionFunctionAbstract implements Reflector
{
    final private 
__clone()
    public 
void __construct(string name)
    public 
string __toString()
    public static 
string export(string namebool 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()
}
?>

Родительский класс ReflectionFunctionAbstract имеет такие же методы, за исключением invoke(), invokeArgs(), export() и isDisabled().

Замечание: getNumberOfParameters() и getNumberOfRequiredParameters() были добавлены в PHP 5.0.3, а invokeArgs() был добавлен в PHP 5.1.0.

Для анализа функции необходимо создать экземпляр класса ReflectionFunction.

Пример #2 Использование класса ReflectionFunction

<?php
/**
 * Простой счетчик
 *
 * @return    int
 */
function counter() 
{
    static 
$c 0;
    return 
$c++;
}

// Создание экземпляра класса ReflectionFunction
$func = new ReflectionFunction('counter');

// Вывод основной информации
printf(
    
"===> Функция %s '%s'\n".
    
"     объявлена в %s\n".
    
"     строки с %d по %d\n",
    
$func->isInternal() ? 'internal' 'user-defined',
    
$func->getName(),
    
$func->getFileName(),
    
$func->getStartLine(),
    
$func->getEndline()
);

// Вывод комментария документации
printf("---> Документация:\n %s\n"var_export($func->getDocComment(), 1));

// Вывод статических переменных, если они есть
if ($statics $func->getStaticVariables())
{
    
printf("---> Статическая переменная: %s\n"var_export($statics1));
}

// Вызов функции
printf("---> Результат вызова: ");
var_dump($func->invoke());


echo 
"\nReflectionFunction::export() результат:\n";
echo 
ReflectionFunction::export('counter');
?>

Замечание: Метод invoke() принимает переменное число аргументов, которые передаются в функцию, также, как в call_user_func().

ReflectionParameter

Класс ReflectionParameter возвращает информацию о параметрах функции или метода.

<?php
class ReflectionParameter implements Reflector
{
    final private 
__clone()
    public 
void __construct(string function, string parameter)
    public 
string __toString()
    public static 
string export(mixed function, mixed parameterbool 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()
}
?>

Замечание: getDefaultValue(), isDefaultValueAvailable() и isOptional() были добавлены в PHP 5.0.3, а isArray() был добавлен в PHP 5.1.0. getDeclaringFunction() и getPosition() были добавлены в PHP 5.2.3.

Для анализа параметров функции необходимо создать экземпляр класса ReflectionFunction или ReflectionMethod и затем использовать метод getParameters() для получения массива параметров.

Пример #3 Использование класса ReflectionParameter

<?php
function foo($a$b$c) { }
function 
bar(Exception $a, &$b$c) { }
function 
baz(ReflectionFunction $a$b 1$c null) { }
function 
abc() { }

// Создание экземпляра класса ReflectionFunction
// с параметром, заданным из командной строки.
$reflect = new ReflectionFunction($argv[1]);

echo 
$reflect;

foreach (
$reflect->getParameters() as $i => $param) {
    
printf(
        
"-- Параметр #%d: %s {\n".
        
"   Класс: %s\n".
        
"   Допускать NULL: %s\n".
        
"   Передан по ссылке: %s\n".
        
"   Обязательный?: %s\n".
        
"}\n",
        
$i
        
$param->getName(),
        
var_export($param->getClass(), 1),
        
var_export($param->allowsNull(), 1),
        
var_export($param->isPassedByReference(), 1),
        
$param->isOptional() ? 'да' 'нет'
    
);
}
?>

ReflectionClass

Класс ReflectionClass позволяет проводить реверс-инжиниринг классов и интерфейсов.

<?php
class ReflectionClass implements Reflector
{
    final private 
__clone()
    public 
void __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 namemixed value)
    public array 
getDefaultProperties()
    public 
bool isIterateable()
    public 
bool implementsInterface(string name)
    public 
ReflectionExtension getExtension()
    public 
string getExtensionName()
}
?>

Замечание: hasConstant(), hasMethod(), hasProperty(), getStaticPropertyValue() и setStaticPropertyValue() были добавлены в PHP 5.1.0, а newInstanceArgs() был добавлен в PHP 5.1.3.

Для анализа класса необходимо создать экземпляр класса ReflectionClass.

Пример #4 Использование класса ReflectionClass

<?php
interface Serializable
{
    
// ...
}

class 
Object
{
    
// ...
}

/**
 * Класс счетчик
 */
class Counter extends Object implements Serializable 
{
    const 
START 0;
    private static 
$c Counter::START;

    
/**
     * Вызвать счетчик
     *
     * @access  public
     * @return  int
     */
    
public function count() {
        return 
self::$c++;
    }
}

// Создание экземпляра класса ReflectionClass
$class = new ReflectionClass('Counter');

// Вывод основной информации
printf(
    
"===> %s%s%s %s '%s' [extends %s]\n" .
    
"     объявлен в %s\n" .
    
"     строки с %d по %d\n" .
    
"     имеет модификаторы %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()))
);

// Вывод комментария из документации
printf("---> Документация:\n %s\n"var_export($class->getDocComment(), 1));

// Вывод тех интерфейсов, которые реализует этот класс
printf("---> Интерфейсы:\n %s\n"var_export($class->getInterfaces(), 1));

// Вывод констант класса
printf("---> Константы: %s\n"var_export($class->getConstants(), 1));

// Вывод свойств класса
printf("---> Свойства: %s\n"var_export($class->getProperties(), 1));

// Вывод методов класса
printf("---> Методы: %s\n"var_export($class->getMethods(), 1));

// Если есть возможность создать экземпляр класса, то создаем его
if ($class->isInstantiable()) {
    
$counter $class->newInstance();

    echo 
'---> $counter инстанцирован? '
    echo 
$class->isInstance($counter) ? 'да' 'нет';

    echo 
"\n---> new Object() инстанцирован? ";
    echo 
$class->isInstance(new Object()) ? 'да' 'нет';
}
?>

Замечание: Метод newInstance() принимает переменное число аргументов, которые передаются в функцию, также, как в call_user_func().

Замечание: $class = new ReflectionClass('Foo'); $class->isInstance($arg) эквивалентно $arg instanceof Foo или is_a($arg, 'Foo').

ReflectionObject

Класс ReflectionObject позволяет проводить реверс-инжиниринг объектов.

<?php
class ReflectionObject extends ReflectionClass
{
    final private 
__clone()
    public 
void __construct(mixed object)
    public 
string __toString()
    public static 
string export(mixed objectbool return)
}
?>

ReflectionMethod

Класс ReflectionMethod позволяет проводить реверс-инжиниринг методов.

<?php
class ReflectionMethod extends ReflectionFunctionAbstract implements Reflector
{
    public 
void __construct(mixed class, string name)
    public 
string __toString()
    public static 
string export(mixed class, string namebool 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()

    
// Унаследовано из 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()
}
?>

Для анализа метода класса необходимо создать экземпляр класса ReflectionMethod.

Пример #5 Использование класса ReflectionMethod

<?php
class Counter
{
    private static 
$c 0;

    
/**
     * Увеличение счетчика
     *
     * @final
     * @static
     * @access  public
     * @return  int
     */
    
final public static function increment()
    {
        return ++
self::$c;
    }
}

// Создание экземпляра класса ReflectionMethod
$method = new ReflectionMethod('Counter''increment');

// Вывод основной информации
printf(
    
"===> %s%s%s%s%s%s%s метод '%s' (which is %s)\n" .
    
"     объявлен в %s\n" .
    
"     строки с %d по %d\n" .
    
"     имеет модификаторы %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()))
);

// Вывод комментария из документации
printf("---> Документация:\n %s\n"var_export($method->getDocComment(), 1));

// Вывод статических переменных, если они есть
if ($statics$method->getStaticVariables()) {
    
printf("---> Статическая переменная: %s\n"var_export($statics1));
}

// Вызов метода
printf("---> Результат вызова: ");
var_dump($method->invoke(NULL));
?>

Замечание: Попытка вызова закрытого, защищенного или абстрактного метода приведет к выбросу исключения из метода invoke().

Замечание: При вызове статических методов нужно передать NULL в качестве первого аргумента invoke(). Для нестатических методов нужно передавать экземпляр класса.

ReflectionProperty

Класс ReflectionProperty позволяет проводить реверс-инжиниринг свойств класса.

<?php
class ReflectionProperty implements Reflector
{
    final private 
__clone()
    public 
void __construct(mixed class, string name)
    public 
string __toString()
    public static 
string export(mixed class, string namebool 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 objectmixed value)
    public 
ReflectionClass getDeclaringClass()
    public 
string getDocComment()
}
?>

Замечание: getDocComment() был добавлен в PHP 5.1.0.

Для анализа свойства класса необходимо создать экземпляр класса ReflectionProperty.

Пример #6 Использование класса ReflectionProperty

<?php
class String
{
    public 
$length  5;
}

// Создание экземпляра класса ReflectionProperty
$prop = new ReflectionProperty('String''length');

// Вывод основной информации о свойстве класса
printf(
    
"===> %s%s%s%s свойство '%s' (которое было %s)\n" .
    
"     имеет модификаторы %s\n",
        
$prop->isPublic() ? ' public' '',
        
$prop->isPrivate() ? ' private' '',
        
$prop->isProtected() ? ' protected' '',
        
$prop->isStatic() ? ' static' '',
        
$prop->getName(),
        
$prop->isDefault() ? 'объявлено во время компиляции' 'создано во время выполнения',
        
var_export(Reflection::getModifierNames($prop->getModifiers()), 1)
);

// Создание экземпляра String
$obj= new String();

// Получение текущего значения
printf("---> Значение: ");
var_dump($prop->getValue($obj));

// Изменение значения
$prop->setValue($obj10);
printf("---> Установка значения 10, новое значение равно: ");
var_dump($prop->getValue($obj));

// Дамп объекта
var_dump($obj);
?>

Замечание: Попытка вызова закрытого или защищенного свойства класса приведет к выбросу исключения.

ReflectionExtension

Класс ReflectionExtension позволяет проводить реверс-инжиниринг расширений. Получить список всех загруженных расширений можно при помощи get_loaded_extensions().

<?php
class ReflectionExtension implements Reflector {
    final private 
__clone()
    public 
void __construct(string name)
    public 
string __toString()
    public static 
string export(string namebool 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()
}
?>

Для анализа расширения необходимо создать экземпляр класса ReflectionExtension. Затем вы сможете вызвать любой из методов, описанных выше.

Пример #7 Использование класса ReflectionExtension

<?php
// Создание экземпляра класса ReflectionProperty
$ext = new ReflectionExtension('standard');

// Вывод основной информации
printf(
    
"Имя           : %s\n" .
    
"Версия        : %s\n" .
    
"Функции       : [%d] %s\n" .
    
"Константы     : [%d] %s\n" .
    
"Директивы INI : [%d] %s\n" .
    
"Классы        : [%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)
);
?>

Наследование классов Reflection

В случае, если вам требуется создать специализированные версии встроенных классов (например, для подсветки HTML при экспорте использовать свойства классов может быть более удобно, чем методы), вы можете наследовать их.

Пример #8 Наследование встроенных классов

<?php
/**
 * Свой класс 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());
    }
}

/**
 * Демо-класс #1
 *
 */
class {
    protected function 
x() {}
}

/**
 * Демо-класс #2
 *
 */
class extends {
    function 
x() {}
}

// Вывод информации
var_dump(new My_Reflection_Method('U''x'));
?>

Замечание: Внимание! Если вы переписываете конструктор, то не забудьте вызывать конструктор родителя _перед_ любым кодом, который вы затем добавите. В случае невыполнения этого условия результат будет следующим: Fatal error: Internal error: Failed to retrieve the reflection object



add a note add a note User Contributed Notes
Reflection
meecrob at k42b3 dot com
20-Jun-2008 12:47
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
fgm at riff dot org
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
?>
Niels Jaeckel
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
rob at endertech dot com
08-Apr-2008 12:34
PHP 5.3 will receive Java's setAccessible() functionality for accessing protected/privates.
Andrea Giammarchi
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 ...
krowork
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.
annonymous
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
Will Mason
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();
?>
killgecNOFSPAM at gmail dot com
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.
massimo at mmware dot it
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"
thiago_mata at yahoo dot com dot br
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 ( <