Podręcznik PHP
Poprzedni | Rozdział 52. Accepting Arguments | Następny

# 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 Tabela 52-1).

Note: All conversion functions expect a **zval as parameter.

Tabela 52-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.

> Notatka: You can find a demonstration of the behavior in `cross_conversion.php` on the accompanying CD-ROM. Rysunek 52-2 shows the output.

Rysunek 52-2. Cross-conversion behavior of PHP.

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 Przykład 52-2.

Przykład 52-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 Tabela 52-2, Tabela 52-3 and Tabela 52-4.

Tabela 52-2. Zend zval Structure

Entry | Description
value | Union containing this variable's contents. See Tabela 52-3 for a description.
type | Contains this variable's type. For a list of available types, see Tabela 52-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.

Tabela 52-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.

Tabela 52-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.

Poprzedni | Spis treści | Następny
Dealing with a Variable Number of Arguments/Optional Parameters | Początek rozdziału | Dealing with Arguments Passed by Reference