Accessing Arguments
To access arguments, it's necessary for each argument to
have a clearly defined type. Again, PHP's extremely dynamic
nature introduces some quirks. Because PHP never does any
kind of type checking, it's possible for a caller to pass any
kind of data to your functions, whether you want it or not.
If you expect an integer, for example, the caller might pass
an array, and vice versa - PHP simply won't notice.
To work around this, you have to use a set of API
functions to force a type conversion on every argument that's
being passed (see 表格 32-1).
Note: All conversion functions expect a **zval as parameter.
表格 32-1. Argument Conversion Functions
Function |
Description |
convert_to_boolean_ex() |
Forces
conversion to a Boolean type. Boolean values remain
untouched. Longs, doubles, and strings containing 0 as well as NULL values will
result in Boolean 0 (FALSE).
Arrays and objects are converted based on the number
of entries or properties, respectively, that they
have. Empty arrays and objects are converted to
FALSE; otherwise, to TRUE. All other values result in
a Boolean 1 (TRUE). |
convert_to_long_ex() |
Forces
conversion to a long, the default integer type. NULL
values, Booleans, resources, and of course longs
remain untouched. Doubles are truncated. Strings
containing an integer are converted to their
corresponding numeric representation, otherwise
resulting in 0. Arrays and
objects are converted to 0
if empty, 1 otherwise. |
convert_to_double_ex() |
Forces
conversion to a double, the default floating-point
type. NULL values, Booleans, resources, longs, and of
course doubles remain untouched. Strings containing a
number are converted to their corresponding numeric
representation, otherwise resulting in 0.0. Arrays and objects are converted
to 0.0 if empty, 1.0 otherwise. |
convert_to_string_ex() |
Forces
conversion to a string. Strings remain untouched.
NULL values are converted to an empty string.
Booleans containing TRUE are converted to "1", otherwise resulting in an empty
string. Longs and doubles are converted to their
corresponding string representation. Arrays are
converted to the string
"Array" and objects to the string "Object". |
convert_to_array_ex(value) |
Forces
conversion to an array. Arrays remain untouched.
Objects are converted to an array by assigning all
their properties to the array table. All property
names are used as keys, property contents as values.
NULL values are converted to an empty array. All
other values are converted to an array that contains
the specific source value in the element with the key
0. |
convert_to_object_ex(value) |
Forces
conversion to an object. Objects remain untouched.
NULL values are converted to an empty object. Arrays
are converted to objects by introducing their keys as
properties into the objects and their values as
corresponding property contents in the object. All
other types result in an object with the property scalar , having the
corresponding source value as content. |
convert_to_null_ex(value) |
Forces
the type to become a NULL value, meaning empty. |
注: You can find a demonstration of the behavior
in cross_conversion.php on the
accompanying CD-ROM. 圖形
32-2 shows the output.
Using these functions on your arguments will ensure type
safety for all data that's passed to you. If the supplied
type doesn't match the required type, PHP forces dummy
contents on the resulting value (empty strings, arrays, or
objects, 0 for numeric values, FALSE for Booleans) to ensure a defined
state.
Following is a quote from the sample module discussed
previously, which makes use of the conversion functions:
zval **parameter;
if((ZEND_NUM_ARGS() != 1) || (zend_get_parameters_ex(1, parameter) != SUCCESS))
{
WRONG_PARAM_COUNT;
}
convert_to_long_ex(parameter);
RETURN_LONG(Z_LVAL_P(parameter));
|
After retrieving the parameter pointer, the parameter value
is converted to a long (an integer), which also forms the
return value of this function. Understanding access to the
contents of the value requires a short discussion of the
zval type, whose definition is shown in
範例
32-2.
範例 32-2. PHP/Zend zval
type definition.
typedef pval zval;
typedef struct _zval_struct zval;
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
struct {
zend_class_entry *ce;
HashTable *properties;
} obj;
} zvalue_value;
struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
unsigned char type; /* active type */
unsigned char is_ref;
short refcount;
};
|
|
Actually, pval (defined in php.h) is only an alias of zval (defined in
zend.h), which in turn refers to
_zval_struct. This is a most interesting structure. _zval_struct is the "master" structure,
containing the value structure, type, and reference
information. The substructure
zvalue_value is a union that contains the variable's
contents. Depending on the variable's type, you'll have to
access different members of this union. For a description of
both structures, see 表格 32-2, 表格
32-3 and 表格
32-4.
表格 32-2. Zend zval
Structure
Entry |
Description |
value |
Union
containing this variable's contents. See
表格 32-3 for a description. |
type |
Contains this variable's type. For a list of
available types, see 表格
32-4. |
is_ref |
0
means that this variable is not a reference; 1 means
that this variable is a reference to another
variable. |
refcount |
The
number of references that exist for this variable.
For every new reference to the value stored in this
variable, this counter is increased by 1. For every
lost reference, this counter is decreased by 1. When
the reference counter reaches 0, no references exist
to this value anymore, which causes automatic freeing
of the value. |
表格 32-3. Zend zvalue_value
Structure
Entry |
Description |
lval |
Use this
property if the variable is of the type IS_LONG,
IS_BOOLEAN, or
IS_RESOURCE. |
dval |
Use this
property if the variable is of the type IS_DOUBLE. |
str |
This
structure can be used to access variables of the type
IS_STRING. The member len contains the string length;
the member val points to the
string itself. Zend uses C strings; thus, the string
length contains a trailing
0x00. |
ht |
This
entry points to the variable's hash table entry if
the variable is an array. |
obj |
Use this
property if the variable is of the type IS_OBJECT. |
表格 32-4. Zend Variable Type Constants
Constant |
Description |
IS_NULL |
Denotes
a NULL (empty) value. |
IS_LONG |
A long
(integer) value. |
IS_DOUBLE |
A double
(floating point) value. |
IS_STRING |
A
string. |
IS_ARRAY |
Denotes
an array. |
IS_OBJECT |
An
object. |
IS_BOOL |
A
Boolean value. |
IS_RESOURCE |
A
resource (for a discussion of resources, see the
appropriate section below). |
IS_CONSTANT |
A
constant (defined) value. |
To access a long you access
zval.value.lval, to access a double you use zval.value.dval, and so on. Because all values
are stored in a union, trying to access data with incorrect
union members results in meaningless output.
Accessing arrays and objects is a bit more complicated
and is discussed later.