PHP では関数とメソッドはだいたい同じ形式で、メソッドは単にスコープが限定された関数でしかありません。 つまり、そのメソッドが属するクラスエントリのスコープになるということです。 クラスエントリについては、このマニュアルの別のページで説明します。 このセクションの目的は、関数やメソッドの内部構造を紹介することです。 関数を定義したり、変数を受け取ったり、PHP プログラマーに値を返したりする方法を説明します。
関数の内部構造は、それほど単純ではありません。
PHP_FUNCTION(hackers_function) { /* 受け取る引数をここで指定します */ long number; /* 引数を受け取ります */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &number) != SUCCESS) { return; } /* 何かの作業をします */ number *= 2; /* 戻り値を設定します */ RETURN_LONG(number); }
プリプロセッサの PHP_FUNCTION(hackers_function)
命令は、
次のような宣言に展開されます。
void zif_hackers_function(INTERNAL_FUNCTION_PARAMETERS)
INTERNAL_FUNCTION_PARAMETERS
はマクロとして定義されており、
次の表のようになります。
型と名前 | 説明 | アクセス用マクロ |
---|---|---|
int ht |
ユーザーから実際に渡されたパラメータの数 | ZEND_NUM_ARGS() |
zval *return_value |
PHP 変数へのポインタ。ここに、ユーザーへの戻り値を設定します。
デフォルトの型は IS_NULL です。
|
RETVAL_* , RETURN_* |
zval **return_value_ptr |
PHP に参照を返すときには、ここに変数へのポインタを設定します。 参照を返すことはお勧めしません。 | |
zval *this_ptr |
メソッド呼び出しの場合は、$this オブジェクトを保持する PHP 変数を指します。
|
getThis() |
int return_value_used |
返り値を呼び出し元が使うかどうかを示すフラグ。 |
For clarity, the fully expanded declaration for PHP_FUNCTION(hackers_function)
looks like:
void zif_hackers_function(int ht, zval* return_value, zval** return_value_ptr, zval* this_ptr, int return_value_used)
The precense of this_ptr
may be confusing, classes are covered in detail in later sections,
suffice to say that PHP_METHOD(MyClass, hackersFunction)
would result in the following declaration:
void zim_MyClass_hackersFunction(INTERNAL_FUNCTION_PARAMETERS)
hackers_function
doesn't do anything useful, it accepts a number using the zend_parse_parameters
API, doubles it, and returns it to the engine.
It is obvious that a normal function would have to do something more complex than double the input, for the purposes of education we are keeping it simple.
On entry to the function return_value
is allocated and initialized to null
, making null
the default return value of any function in PHP.
If zend_parse_parameters
does not recieve what is specified by the Hacker
as the correct arguments, and the arguments recieved cannot be converted
to conform with type_spec
an error will be raised, and by convention, the Hacker
should return
immediately.
注意:
Arrays
,Objects
, andResources
cannot be converted.
int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...) |
int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...) |
int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...) |
注意:
zend_parse_parameter
is available from version 5.5, it behaves likezend_parse_parameters_ex
except that instead of reading the arguments from the stack, it receives a single zval to convert, which may be changed in place.
注意:
flags
is intended to be a mask, currently onlyZEND_PARSE_PARAMS_QUIET
will have any impact (supress warnings)
The variable arguments recieved by these API functions are expected to be the address of C variables, and should be considered the output of the zend_parse_parameters
API functions.
Spec | Type | Locals |
---|---|---|
a | array |
zval* |
A | array or object |
zval* |
b | boolean |
zend_bool |
C | class |
zend_class_entry* |
d | double |
double |
f | function |
zend_fcall_info* , zend_fcall_info_cache* |
h | array |
HashTable* |
H | array or object |
HashTable* |
l | long |
long |
L | long (limits out-of-range LONG_MAX/LONG_MIN) |
long |
o | object |
zval* |
O | object (of specified zend_class_entry ) |
zval* , zend_class_entry* |
p | string (a valid path) |
char* , int |
r | resource |
char* |
s | string |
char* , uint |
z | mixed |
zval* |
Z | mixed |
zval** |
注意:
Where the type specifier is
O
, the localzend_class_entry*
is to be considered input (part of the type spec) tozend_parse_parameter
Spec | Description |
---|---|
* | a variable number of argument of the preceeding type, 0 or more |
+ | a variable number of argument of the preceeding type, 1 or more |
| | indicates that the remaining parameters are optional |
/ | SEPARATE_ZVAL_IF_NOT_REF on the parameter it follows |
! |
the preceeding parameter can be of the specified type or null
For 'b', 'l' and 'd', an extra argument of type zend_bool* must be passed after
the corresponding bool* , long* or double*
addresses which will be set true if null is recieved.
|
注意:
Consult
README.PARAMETER_PARSING_API
included in source distributions for more information on parsing parameters
Once the Hacker's
function has executed whatever it was implemented to execute, it is time to set the return_value
for the engine.
The RETURN_
and RETVAL_
macros are just wrappers around Z_*_P
macros that work with return_value
.
注意:
RETURN_
macros cause execution to leave the function immediately (ie:return;
), whileRETVAL_
macros allow execution to continue afterreturn_value
has been set.
The Hacker
should now have a reasonable understanding of the anatomy of a function, and to some degree, the anatomy of a method.