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