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

Запрос аргументов

Новый 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, &param) == 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 - они иллюстрируют каждый представленный случай.


Назад Оглавление Вперёд
Приём аргументов Вверх Старый способ запроса аргументов (не рекомендуется)


Наш баннер
Вы можете установить наш баннер на своем сайте или блоге, скопировав этот код:
RSS новости