|  | Для доступа к аргументам необходимо иметь для каждого аргумента ясно 
определённый тип. Предельно динамичная природа PHP позволяет прибегать к 
некоторым трюкам. Поскольку PHP никогда не делает никакой проверки типа, 
вызыватель может передавать в функции любой вид данных, хотите вы этого или нет.
Если вы ожидаете integer, например, вызыватель может передать массив, и наоборот - PHP этого не заметит. Чтобы работать в этих условиях, вы должны использовать набор API-функций для 
форсирования конвертации типов каждого передаваемого аргумента (см. Таблицу 9.4). Примечание: Все функции конвертации ожидают в качестве параметра **zval. Рисунок 33-3. Таблица 9.4. Функции конвертации аргументов| Функция | Описание | 
|---|
 | convert_to_boolean_ex() | Форсирует конвертацию в Boolean. Boolean-значения не изменяются. Long, double и 
string, содержащие значения 0 и NULL, дают Boolean 0 (FALSE). Массивы и
объекты конвертируются на основе количества вхождений или свойств,
соответственно. Пустые массивы и объекты конвертируются в FALSE; другие - в TRUE. Все другие значения дают Boolean
1 (TRUE). |  | convert_to_long_ex() | Форсирует конвертацию в long, целочисленный тип по умолчанию.
NULL, Boolean, ресурсы и, разумеется, long-значения не изменяются.
Double усекаются. String, содержащие integer, конвертируются в 
соответствующие числовые представления, иначе - дают 0. Массивы и объекты конвертируются в
0, если пустые, иначе - в  1. |  | convert_to_double_ex() | Форсирует конвертацию в double, тип по умолчанию с плавающей точкой. NULL, 
Boolean, ресурсы, long и double не изменяются. String, содержащие 
integer, конвертируются в соответствующие числовые представления, иначе - дают 0.0.
Массивы и объекты конвертируются в 0.0, если пустые, иначе - в 1.0. |  | convert_to_string_ex() | Форсирует конвертацию в string. String остаются без изменений.
NULL конвертируются в пустые строки. Boolean TRUE конвертируются в "1", иначе дают пустую
строку. Long и double конвертируются в their соответствующие 
строковые представления. Массивы конвертируются в строку "Array", а объекты - в строку "Object". |  | convert_to_array_ex(value) | Форсирует
конвертацию в массив. Массивы остаются без изменений.
Объекты конвертируются в массив с присвоением всех свойств таблице 
массива. Имена свойств используются как ключи, содержание свойств 
- как значения. NULL конвертируются в пустой массив. Все другие 
значения конвертируются в массив, который содержит специфическое 
исходное значение в элементе с ключом 0. |  | convert_to_object_ex(value) | Форсирует конвертацию в объект. Объекты остаются без изменений.
NULL конвертируются в пустой объект. Массивы конвертируются в объекты с ключами 
как свойствами и значениями свойств как содержимым свойств. Все другие типы дают объект со свойством
scalar, имеющим исходное значение в качестве содержимого. |  
| convert_to_null_ex(value) | Форсирует типы в NULL, что означает пустой. | 
 Примечание: Вы можете найти демо в файле cross_conversion.php
на сопутствующем CD-ROM. На Рисунке 9.5 показан вывод.
 Рисунок 33-4. Рисунок 9.5. Конвертация в PHP. 
 Использование этих функций с вашими аргументами гарантирует сохранение типа для 
всех данных, передаваемых вам. Если предлагаемый тип не соответствует 
требуемому типу, PHP форсирует содержимое-болванку (пустые строки, массивы или объекты, 0 для
числовых значений, FALSE для Boolean), чтобы гарантировать сохранение статус. Далее идёт выдержка из модуля-сэмпла, обсуждённого ранее, в которой 
используются функции конвертации: | 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)); | 
 После получения указателя параметра, значение параметра конвертируется в long (integer), 
которое формирует также return-значение данной функции. Понимание процесса 
доступа к содержимому значения требует небольшого обсуждения типа zval, определение которого
показано в Листинге 9.8. 
Рисунок 33-5.
Листинг 9.8. Определение PHP/Zend-типа zval. | typedef pval zval;
typedef struct _zval_struct zval;
typedef union _zvalue_value {
	long lval;				/* long-значение */
	double dval;				/* double-значение */
	struct {
		char *val;
		int len;
	} str;
	HashТаблица *ht;				/* значение хэш-таблицы */
	struct {
		zend_class_entry *ce;
		HashТаблица *properties;
	} obj;
} zvalue_value;
struct _zval_struct {
	/* Variable information */
	zvalue_value value;		/* значение */
	unsigned char type;	/* активный тип */
	unsigned char is_ref;
	short refcount;
}; | 
 В действительности pval (определённый в php.h)
это лишь псевдоним для zval (определённом в zend.h),
который, в свою очередь, ссылается на _zval_struct. Это самая интересная структура.
_zval_struct это "мастер"-структура, содержащая структуру значения, тип и справочную 
информацию. Подструктура zvalue_value это union (объединение), содержащее содержимое переменной.
В зависимости от типа переменной, вы должны получать доступ к разным членам 
этого union. Описание обеих структур см. в Таблицах 9.5, 9.6 и 9.7. Рисунок 33-6. Таблица 9.5. Zend-структура zval| Вхождение | Описание | 
|---|
 | value | Union, содержащее содержимое данной переменной. См. описание в Таблице 9.6. |  | type | Содержит тип переменной. Список доступных типов см. в Таблице 9.7. |  | is_ref | 0 означает, что эта переменная не является ссылкой; 1 означает, что эта 
переменная является ссылкой на другую переменную. |  | refcount | Количество существующих ссылок для данной переменной.
Для каждой новой ссылки на значение, хранимое в этой переменной, 
этот счётчик увеличивается на 1. Для каждой потерянной ссылки - 
этот счётчик уменьшается на 1. Когда счётчик ссылок достигает 0, 
для данной переменной больше не существует ни одной ссылке, что 
вызывает автоматическое освобождение переменной. | 
 Рисунок 33-7. Таблица 9.6. Zend-структура zvalue_value| Вхождение | Описание | 
|---|
 | lval | Используйте это свойство, если переменная имеет тип
IS_LONG, IS_BOOLEAN или IS_RESOURCE. |  | dval | Используйте это свойство, если переменная имеет тип IS_DOUBLE. |  | str | Эта структура может использоваться для доступа к
переменным типа IS_STRING. Член len содержит длину строки; член val
указывает на саму строку. Zend использует C-строки; таким образом, длина строки включает также ведомый
0x00. |  | ht | Это вхождение указывает
на вхождение переменной в хэш-таблице, если переменная является массивом. |  
| objИспользуйте это свойство, если переменная имеет тип
IS_OBJECT. | 
 Рисунок 33-8. Таблица 9.7. Константы типов Zend-переменных
| Константа | Описание | 
|---|
 | IS_NULL | Обозначает NULL (пустое) значение. |  | IS_LONG | Значение long (integer). |  
| IS_DOUBLE | double (floating point). |  
| IS_STRING | Строка. |  | IS_ARRAY | Массив. |  | IS_OBJECT | Объект. |  | IS_BOOL | Булево значение. |  | IS_RESOURCE | Ресурс (обсуждение ресурсов см. далее в соответствующем разделе). |  | IS_CONSTANT | Константное (определённое) значение. | 
 Для доступа к long вы выполняете доступ к zval.value.lval, для доступа
к double вы используете zval.value.dval, и так далее. Поскольку все значения хранятся в union,
попытка доступа к данным через некорректный член union приведёт к бессмысленному выводу. Доступ к массивам и объектам немного сложнее и будет рассмотрен позже. |  |