Table of Contents
This is no full book; I just wrote the reflection chapter because there was no documentation about it and I had a hard time figuring it out. Perhaps I'll write more, but don't rely on that.
This document is licensed under a Creative Commons license.
Table of Contents
Unlike PHP4, PHP5 doesn't just let you read all defined classes and class methods, but even such things like method parameters, parameter types, static class variables, ...
By default, PHP knows many things about your extension and the default functions, but the most cool thing is missing: The class parameters and parameter types. You as an extension author have to write some additional code to provide the necessary information for PHP to get it. This small howto shows you what you need.
First, let's have a look at the SPL source code in
ext/spl/spl_directory.c
:
SPL_METHOD(DirectoryIterator, openFile) { ... } ... static ZEND_BEGIN_ARG_INFO_EX(arginfo_dir_openFile, 0, 0, 0) ZEND_ARG_INFO(0, open_mode) ZEND_ARG_INFO(0, use_include_path) ZEND_ARG_INFO(0, context) ZEND_END_ARG_INFO(); ... static zend_function_entry spl_ce_dir_class_functions[] = { SPL_ME(DirectoryIterator, __construct, arginfo_dir___construct, ZEND_ACC_PUBLIC) SPL_ME(DirectoryIterator, rewind, NULL, ZEND_ACC_PUBLIC) SPL_ME(DirectoryIterator, valid, NULL, ZEND_ACC_PUBLIC) ... SPL_ME(DirectoryIterator, isDot, NULL, ZEND_ACC_PUBLIC) SPL_ME(DirectoryIterator, openFile, arginfo_dir_openFile, ZEND_ACC_PUBLIC) SPL_MA(DirectoryIterator, __toString, DirectoryIterator, getFilename, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} };
At first, the method openFile
of class
DirectoryIterator
is defined. Is it registered as
official function with zend_function_entry
, so
that PHP knows that it can be used.
Now if you look at the
SPL_ME(...)
entries in the function registration table, you will see a
NULL as third parameter in many lines. This means that
there is no extra parameter information. However, for
openFile
, it is
arginfo_dir_openFile
. It tells PHP to look at
the argument information structure with name
arginfo_dir_openFile
.
An argument information structure looks like this:
static ZEND_BEGIN_ARG_INFO(<funcname>, 0) ZEND_ARG_INFO(0, parametername1); ... (more parameter definitions) ZEND_END_ARG_INFO();
There are two different ARG_INFO structures:
ZEND_BEGIN_ARG_INFO_EX(<funcname>, 0, 0, <number of required parameters>)
and
ZEND_BEGIN_ARG_INFO(<funcname>, 0)
The first one allows you to define the number of required parameters as the fourth parameter. If you don't need this (all are required), you should use the second one for simplicity's sake.
It's good practice to use the following scheme for argument
information function names:
arginfo_<classname>_<methodname>
The parameter definition itself can be done with two different functions, too:
ZEND_ARG_OBJ_INFO(0, <parametername>, <parameterclass>, <allow_null>) ZEND_ARG_INFO(0, <parametername>)
With the first one you define the name of the parameter (e.g.
file_handle
or resource
) and as
third parameter the class of which the parameter has to be. Pass
1
as fourth parameter if you want to allow NULL
values, 0
otherwise.
Note that
PHP uses this information for extra validation, so PHP will print out
and error if you pass a parameter of a different type in your php
scripts or a null when it's not explicitely allowed.
If you have a mixed type or don't want to specify it, use the second, simple one.
If you want to have a look at the reflection implementation in
the zend engine, you could begin at
Zend/zend_API.h
, line 60 and
Zend/zend_reflection_api.c
.
There is a PHP5+PHP-Gtk2 reflection browser at cweiske.de which does the whole thing.
First, use get_declared_classes()
to
get all classes known to your php installation.
Then make a ReflectionClass
object for
the class you want to inspect:
$refl = new ReflectionClass('ReflectionClass');
Now you can use the function getMethods()
to retreive all the functions ReflectionClass
provides:
$methods = $refl->getMethods();
You have an array of ReflectionMethod
objects now which you can inspect further.
getParameters()
will give you all the defined
parameters, and getNumberOfRequiredParameters()
the non-optional ones.
Play around with reflection; there is almost nothing you can't reflect - even line numbers of (userland) class declarations can be read.