Учебник РНР
Назад Глава 34. Создание Переменных Вперёд

Массивы

Массивы хранятся с использованием внутренних хэш-таблиц Zend, доступ к которым может быть получен с помощью zend_hash_*() API. Для каждого создаваемого вами массива вам понадобится дескриптор новой хэш таблицы, который хранится в члене ht контейнера zval.value.

Имеется API, предназначенный исключительно для создания массивов.
Для создания нового массива вы вызываете array_init().

zval *new_array; MAKE_STD_ZVAL(new_array); if(array_init(new_array) != SUCCESS) { // здесь обработка ошибок }

Если array_init() не смогла создать новый массив, она возвращает FAILURE.

Для добавления в массив новых элементов вы можете использовать многочисленные функции, в зависимости от того, что нужно сделать. В Таблицах 9.8, 9.9 и 9.10 описаны эти функции. Все функции возвращают FAILURE при неудаче и SUCCESS при успешном выполнении.

Рисунок 34-3. Таблица 9.8. Zend's API для ассоциативных массивов
Примечание: Все функции в Таблице 9.8 работают с массивом "array" с ключом "key". Строка ключа не должна находиться во внутренней памяти Zend; она будет дублироваться API.

Функция Описание
add_assoc_long(zval *array, char *key, longn);() Добавляет элемент типа long.
add_assoc_unset(zval *array, char *key);() Добавляет unset-элемент.
add_assoc_bool(zval *array, char *key, int b);() Добавляет Булев элемент.
add_assoc_resource(zval *array, char *key,
int r);()
Добавляет ресурс к массиву.
add_assoc_double(zval *array, char *key,
double d);()
Добавляет значение с плавающей точкой.
add_assoc_string(zval *array, char *key,
char *str, int duplicate);()
Добавляет строку к массиву. Флаг duplicate специфицирует, копируется ли содержимое строки во внутреннюю память Zend.
add_assoc_stringl(zval *array, char *key,
char *str, uint length, int duplicate);()
Добавляет строку необходимого размера length к массиву. Иначе поведение как у add_assoc_string()().
Рисунок 34-4. Таблица 9.9. Zend's API для индексированных массивов , Часть 1
Примечание: Все функции в Таблице 9.9 работают с массивом "array" с индексом "idx". Индекс - всегда integer.

Функция Описание
add_index_long(zval *array, uint idx, long n);() Добавляет элемент типа long.
add_index_unset(zval *array, uint idx);() Добавляет unset-элемент.
add_index_bool(zval *array, uint idx, int b);() Добавляет Булев элемент.
add_index_resource(zval *array, uint idx,
int r);()
Добавляет ресурс к массиву.
add_index_double(zval *array, uint idx,
double d);()
Добавляет значение с плавающей точкой.
add_index_string(zval *array, uint idx,
char *str, int duplicate);()
Добавляет строку к массиву. Флаг duplicate специфицирует, копируется ли содержимое строки во внутреннюю память Zend.
add_index_stringl(zval *array, uint idx,
char *str, uint length, int duplicate);()
Добавляет строку необходимого размера length к массиву. Эта функция работает быстрее и безопасна в бинарном режиме. Иначе поведение как у add_index_string()().
Рисунок 34-5. Таблица 9.10. Zend's API для индексированных массивов , Часть 2
Примечание: Все функции в Таблице 9.10 работают с массивом "array". Эти функции автоматически генерируют новый индекс на основе наибольшего индекса, найденного в массиве.

Функция Описание
add_next_index_long(zval *array, long n);() Добавляет элемент типа long.
add_next_index_unset(zval *array);() Добавляет unset-элемент.
add_next_index_bool(zval *array, int b);() Добавляет Булев элемент.
add_next_index_resource(zval *array, int r);() Добавляет ресурс к массиву.
add_next_index_double(zval *array,
double d);()
Добавляет значение с плавающей точкой.
add_next_index_string(zval *array, char *str, int duplicate);() Добавляет строку к массиву. Флаг duplicate специфицирует, копируется ли содержимое строки во внутреннюю память Zend.
add_next_index_stringl(zval *array, char *str, uint length, int duplicate);() Добавляет строку необходимого размера length к массиву. Эта функция работает быстрее и безопасна в бинарном режиме. Иначе поведение как у add_index_string()().

Все эти функции предоставляют удобную абстракцию API внутреннего хэша Zend. Разумеется, вы можете также использовать функции хэша напрямую - например, если у вас уже есть размещённый zval-контейнер, который вы хотите вставить в массив. Это делается с помощью zend_hash_update()() для ассоциативный массивов (см. Листинг 9.12) и zend_hash_index_update() - для индексированных массивов (см. Листинг 9.13):

Рисунок 34-6. Листинг 9.12. Добавление элемента в ассоциативный массив.
zval *new_array, *new_element; char *key = "element_key"; MAKE_STD_ZVAL(new_array); MAKE_STD_ZVAL(new_element); if(array_init(new_array) == FAILURE) { // здесь обработка ошибок } ZVAL_LONG(new_element, 10); if(zend_hash_update(new_array->value.ht, key, strlen(key) + 1, (void *)&new_element, sizeof(zval *), NULL) == FAILURE) { // здесь обработка ошибок }
Рисунок 34-7. Листинг 9.13. Добавление элемента в индексированный массив.
zval *new_array, *new_element; int key = 2; MAKE_STD_ZVAL(new_array); MAKE_STD_ZVAL(new_element); if(array_init(new_array) == FAILURE) { // здесь обработка ошибок } ZVAL_LONG(new_element, 10); if(zend_hash_index_update(new_array->value.ht, key, (void *)&new_element, sizeof(zval *), NULL) == FAILURE) { // здесь обработка ошибок }

Для эмуляции функциональности add_next_index_*() вы можете использовать:

zend_hash_next_index_insert(ht, zval **new_element, sizeof(zval *), NULL)
Примечание: для возвращения массивов из функций используйте array_init() и все последующие акции с предопределённой переменной return_value (заданной в качестве аргумента в вашей экспортируемой функции; см. ранее обсуждение интерфейса вызова). Вы не должны использовать при этом MAKE_STD_ZVAL.

Подсказка: чтобы исключить необходимость каждый раз записывать new_array->value.ht, вы можете использовать HASH_OF(new_array), что рекомендуется также по соображениям стиля и обеспечения совместимости.


Назад Оглавление Вперёд
Booleans/Булевы Вверх Объекты