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
Tabla 32_1)_
Note: All conversion functions expect a
**zval as parameter_
Tabla 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_ |
Nota:
You can find a demonstration of the behavior in
cross_conversion_php on the accompanying
CD_ROM_ Figura 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, ¶meter) != 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
Ejemplo 32_2_
Ejemplo 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
Tabla 32_2,
Tabla 32_3 and
Tabla 32_4_
Tabla 32_2_ Zend zval Structure
| Entry | Description |
| value |
Union containing this variable's contents_ See
Tabla 32_3 for a description_
|
| type |
Contains this variable's type_ For a list of available
types, see Tabla 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_
|
Tabla 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_ |
Tabla 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_