Для доступа к аргументам необходимо иметь для каждого аргумента ясно
определённый тип. Предельно динамичная природа 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), чтобы гарантировать сохранение статуса.
Далее идёт выдержка из модуля-сэмпла, обсуждённого ранее, в которой
используются функции конвертации:
После получения указателя параметра, значение параметра конвертируется в 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,
для данной переменной больше не существует ни одной ссылке, что
вызывает автоматическое освобождение переменной.
Используйте это свойство, если переменная имеет тип
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 приведёт к бессмысленному выводу.
Доступ к массивам и объектам немного сложнее и будет рассмотрен позже.