|
Новый API разбора параметров: В этой главе задокументирован новый Zend
API разбора параметров, автор Andrei Zmievski. Он был введён в период между PHP 4.0.6 и 4.1.0.
Разбор параметров это самая распространённая и утомительная операция.
Было бы удобно также иметь стандартизованную проверку ошибок и механизм
сообщений. Начиная с PHP 4.1.0, имеется способ делать всё это с помощью
нового API разбора параметров. Он значительно упрощает процесс получения
параметров, но недостаток его в том, что он не может использоваться в
функциях, ожидающих переменное количество параметров. но поскольку
большинство функций не входят в эту категорию, этот API разбора рекомендуется как новый стандартный способ.
Прототип функции разбора параметров таков:
int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...); |
Первый аргумент этой функции это количество реально переданных функции параметров, так что
ZEND_NUM_ARGS() может использоваться здесь. Второй параметр всегда должен быть макросом TSRMLS_CC.
Третий аргумент это строка, специфицирующая количество и типы аргументов,
ожидаемых вашей функцией, аналогично тому, как строка форматирования
printf специфицирует количество и формат выводимых значений, с
которыми она должна работать. И, наконец, остальные аргументы это
указатели на переменные, которые должны принимать значения от параметров.
zend_parse_parameters() выполняет также, где возможно, конвертацию типов, так что вы всегда получаете
данные в том формате, который запросили. Любой скалярный тип может быть
конвертирован в другой, но конвертация между сложными типами (массивами, объектами и ресурсами) и скалярными типами не допускается.
Если параметр может быть успешно получен и в процессе конвертации не было ошибок, функция возвратит
SUCCESS, иначе - FAILURE. Функция выводит информативные сообщения об ошибках, если количество
полученных параметров не совпадает с запрашиваемым количеством или если
конвертация типов не может быть выполнена.
Вот некоторые примеры сообщений об ошибках:
Warning! - ini_get_all() requires at most 1 parameter, 2 given
Warning! - wddx_deserialize() expects parameter 1 to be string, array given |
Естественно, каждое сообщение об ошибке сопровождается именем файла и строкой, в которой ошибка возникла.
Вот полный список спецификаторов типов: l - long d - double
s - string/строка (с возможным нулевым количеством байтов) и её длина
b - boolean r - ресурс, хранимый в zval*
a - array/массив, хранимый в zval* o - object/объект (любого класса), хранимый в
zval* O - object/объект (класса, специфицированного вхождением класса), хранимый в
zval* z - текущий zval*
Следующие символы также имеют значение в строке спецификатора:| - указывает, что оставшиеся параметры являются необязательными. Переменные для
хранения, соответствующие этим параметрам, должны быть инициализированы
значениями по умолчанию расширением, поскольку они не будут затронуты
разбирающей функцией, если параметры не переданы. / - разбирающая функция вызывает
SEPARATE_ZVAL_IF_NOT_REF() для следующего за ней параметра, чтобы предоставить копию этого параметра,
если только это не ссылка. ! - следующий за ним параметр может быть специфицированного типа или
NULL (применяется только к a, o, O, r или z). Если значение NULL передаётся пользователем,
хранимый указатель будет установлен в NULL.
Лучше всего показать работу этой функции на примерах:
/* Получить long, string и её длину и zval. */
long l;
char *s;
int s_len;
zval *param;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"lsz", &l, &s, &s_len, ¶m) == FAILURE) {
return;
}
* Получить объект класса, специфицированного my_ce, и необязательное double. */
zval *obj;
double d = 0.5;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"O|d", &obj, my_ce, &d) == FAILURE) {
return;
}
/* Получить объект или null и массив.
Если null передаётся для объекта, obj будет установлен в NULL. */
zval *obj;
zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O!a", &obj, &arr) == FAILURE) {
return;
}
/* Получить массив. */
zval *arr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &arr) == FAILURE) {
return;
}
/* Получить только первые три параметра (используется для varargs-функций). */
zval *z;
zend_bool b;
zval *r;
if (zend_parse_parameters(3, "zbr!", &z, &b, &r) == FAILURE) {
return;
} |
Обратите внимание, что в третьем примере мы передаём 3 для числа принимаемых получаемых параметров вместо
ZEND_NUM_ARGS(). Это позволяет получать наименьшее количество параметров, если наша функция
ожидает их переменное количество. Разумеется, если вы хотите работать с
остальными параметрами, вы должны использовать zend_get_parameters_array_ex() для их получения.
Функция-разборщик имеет расширенную версию, которая имеет
дополнительный аргумент flags, управляющий её работой.
int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...); |
Единственный флаг, который в настоящее время можно передавать, это ZEND_PARSE_PARAMS_QUIET,
который указывает функции не выводить никаких сообщений об ошибках в
ходе операции. Это можно использовать в функциях, которые ожидают
несколько наборов совершенно разных аргументов, но вам придётся самостоятельно выводить сообщение об ошибке.
Например, вот как можно получить набор из трёх long или строку:
long l1, l2, l3;
char *s;
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC,
"lll", &l1, &l2, &l3) == SUCCESS) {
/* работа с long */
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS(), "s", &s, &s_len) == SUCCESS) {
/* работа с string */
} else {
php_error(E_WARNING, "%s() takes either three long values or a string as argument",
get_active_function_name(TSRMLS_C));
return;
} |
С помощью рассмотренных способов получения параметров функцией вы
должны были получить хорошее представление об этом процессе.
Дополнительные примеры см. в исходном коде расширений, которые
поставляются с PHP - они иллюстрируют каждый представленный случай. | |