Учебник РНР
Назад Глава 33. Приём аргументов Вперёд

Доступ к аргументам

Для доступа к аргументам необходимо иметь для каждого аргумента ясно определённый тип. Предельно динамичная природа 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, &parameter) != 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
Используйте это свойство, если переменная имеет тип IS_OBJECT.
Вхождение Описание
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 приведёт к бессмысленному выводу.

Доступ к массивам и объектам немного сложнее и будет рассмотрен позже.


Назад Оглавление Вперёд
Работа с переменным количеством аргументов/необязательных параметров Вверх Работа с аргументами, передаваемыми по ссылке