Доступ к Аргументам
Доступ к аргументам
Для доступа к аргументам необходимо иметь для каждого аргумента ясно определённый тип. Предельно динамичная природа 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 |
Рисунок 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 приведёт к бессмысленному выводу.
Доступ к массивам и объектам немного сложнее и будет рассмотрен позже.