Учебник РНР
НазадГлава 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
ВхождениеОписание
valueUnion, содержащее содержимое данной переменной. См. описание в Таблице 9.6.
typeСодержит тип переменной. Список доступных типов см. в Таблице 9.7.
is_ref0 означает, что эта переменная не является ссылкой; 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_DOUBLEdouble (floating point).
IS_STRINGСтрока.
IS_ARRAYМассив.
IS_OBJECT Объект.
IS_BOOLБулево значение.
IS_RESOURCEРесурс (обсуждение ресурсов см. далее в соответствующем разделе).
IS_CONSTANTКонстантное (определённое) значение.

Для доступа к long вы выполняете доступ к zval.value.lval, для доступа к double вы используете zval.value.dval, и так далее. Поскольку все значения хранятся в union, попытка доступа к данным через некорректный член union приведёт к бессмысленному выводу.

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


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