mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-13 22:06:51 +08:00

* Replace https://secure.php.net with https://www.php.net * Replace http://www.php.net with https://www.php.net
350 lines
16 KiB
Markdown
350 lines
16 KiB
Markdown
ArrayHelper
|
||
===========
|
||
Вдобавок к [богатому набору функций](https://www.php.net/manual/ru/book.array.php) для работы с массивами, которые есть в самом PHP, хелпер Yii Array предоставляет свои статические функции - возможно они могут быть вам полезны.
|
||
|
||
|
||
## Получение значений <span id="getting-values"></span>
|
||
|
||
Извлечение значений из массива, объекта или структуры состоящей из них обоих с помощью стандартных средств PHP является довольно скучным занятием. Сначала вам нужно проверить есть ли соответствующий ключ с помощью `isset`, и если есть – получить, если нет – подставить значение по умолчанию.
|
||
|
||
```php
|
||
class User
|
||
{
|
||
public $name = 'Alex';
|
||
}
|
||
|
||
$array = [
|
||
'foo' => [
|
||
'bar' => new User(),
|
||
]
|
||
];
|
||
|
||
$value = isset($array['foo']['bar']->name) ? $array['foo']['bar']->name : null;
|
||
```
|
||
|
||
Yii предлагает очень удобный метод для таких случаев:
|
||
|
||
```php
|
||
$value = ArrayHelper::getValue($array, 'foo.bar.name');
|
||
```
|
||
|
||
Первый аргумент – массив или объект из которого мы извлекаем значение. Второй аргумент определяет как будут извлекаться данные и может выглядеть как один из таких вариантов:
|
||
- Имя ключа массива или свойства объекта, значение которого нужно вернуть
|
||
- Путь к нужному значению, разделенный точками, как в примере выше
|
||
- Callback-функция, возвращающая значение
|
||
|
||
Callback-функция должна выглядеть примерно так:
|
||
|
||
```php
|
||
$fullName = ArrayHelper::getValue($user, function ($user, $defaultValue) {
|
||
return $user->firstName . ' ' . $user->lastName;
|
||
});
|
||
```
|
||
|
||
Третий необязательный аргумент определяет значение по умолчанию. Если не установлен – равен `null`. Используется так:
|
||
|
||
```php
|
||
$username = ArrayHelper::getValue($comment, 'user.username', 'Unknown');
|
||
```
|
||
|
||
|
||
## Запись значений <span id="setting-values"></span>
|
||
|
||
```php
|
||
$array = [
|
||
'key' => [
|
||
'in' => ['k' => 'value']
|
||
]
|
||
];
|
||
|
||
ArrayHelper::setValue($array, 'key.in', ['arr' => 'val']);
|
||
// путь для записи значения в `$array` можно указать как массив
|
||
ArrayHelper::setValue($array, ['key', 'in'], ['arr' => 'val']);
|
||
```
|
||
|
||
В результате исходное значение `$array['key']['in']` будет перезаписано новым
|
||
|
||
```php
|
||
[
|
||
'key' => [
|
||
'in' => ['arr' => 'val']
|
||
]
|
||
]
|
||
```
|
||
|
||
Если путь содержит несуществующий ключ, то он будет создан
|
||
|
||
```php
|
||
// Если `$array['key']['in']['arr0']` не пустой, то значение будет добавлено в массив
|
||
ArrayHelper::setValue($array, 'key.in.arr0.arr1', 'val');
|
||
|
||
// если необходимо полностью переопределить значение `$array['key']['in']['arr0']`
|
||
ArrayHelper::setValue($array, 'key.in.arr0', ['arr1' => 'val']);
|
||
```
|
||
|
||
Результатом будет следующим:
|
||
|
||
```php
|
||
[
|
||
'key' => [
|
||
'in' => [
|
||
'k' => 'value',
|
||
'arr0' => ['arr1' => 'val']
|
||
]
|
||
]
|
||
]
|
||
```
|
||
|
||
|
||
## Изъять значение из массива <span id="removing-values"></span>
|
||
|
||
Если вы хотите получить значение и тут же удалить его из массива, вы можете использовать метод `remove`
|
||
|
||
```php
|
||
$array = ['type' => 'A', 'options' => [1, 2]];
|
||
$type = ArrayHelper::remove($array, 'type');
|
||
```
|
||
|
||
После выполнения этого кода переменная `$array` будет содержать `['options' => [1, 2]]`, а в переменной `$type` будет значение `А`. В отличие от метода `getValue`, метод `remove` поддерживает только простое имя ключа.
|
||
|
||
|
||
## Проверка наличия ключей <span id="checking-existence-of-keys"></span>
|
||
|
||
`ArrayHelper::keyExists` работает так же, как и стандартный [array_key_exists](https://www.php.net/manual/ru/function.array-key-exists.php),
|
||
но также может проверять ключи без учёта регистра:
|
||
|
||
```php
|
||
$data1 = [
|
||
'userName' => 'Alex',
|
||
];
|
||
|
||
$data2 = [
|
||
'username' => 'Carsten',
|
||
];
|
||
|
||
if (!ArrayHelper::keyExists('username', $data1, false) || !ArrayHelper::keyExists('username', $data2, false)) {
|
||
echo "Пожалуйста, укажите имя пользователя.";
|
||
}
|
||
```
|
||
|
||
## Извлечение столбцов <span id="retrieving-columns"></span>
|
||
|
||
Часто нужно извлечь столбец значений из многомерного массива или объекта. Например, список ID.
|
||
|
||
```php
|
||
$array = [
|
||
['id' => '123', 'data' => 'abc'],
|
||
['id' => '345', 'data' => 'def'],
|
||
];
|
||
$ids = ArrayHelper::getColumn($array, 'id');
|
||
```
|
||
|
||
Результатом будет `['123', '345']`.
|
||
|
||
Если нужны какие-то дополнительные трансформации или способ получения значения специфический, вторым аргументом может быть анонимная функция:
|
||
|
||
```php
|
||
$result = ArrayHelper::getColumn($array, function ($element) {
|
||
return $element['id'];
|
||
});
|
||
```
|
||
|
||
## Переиндексация массивов <span id="reindexing-arrays"></span>
|
||
|
||
|
||
Чтобы проиндексировать массив в соответствии с определенным ключом, используется метод `index` . Входящий массив должен
|
||
быть многомерным или массивом объектов. Ключом может быть имя ключа вложенного массива, имя свойства объекта или
|
||
анонимная функция, которая будет возвращать значение ключа по переданному массиву.
|
||
|
||
Если значение ключа равно `null`, то соответствующий элемент массива будет опущен и не попадет в результат.
|
||
|
||
```php
|
||
$array = [
|
||
['id' => '123', 'data' => 'abc'],
|
||
['id' => '345', 'data' => 'def'],
|
||
];
|
||
$result = ArrayHelper::index($array, 'id');
|
||
// результат будет таким:
|
||
// [
|
||
// '123' => ['id' => '123', 'data' => 'abc'],
|
||
// '345' => ['id' => '345', 'data' => 'def'],
|
||
// ]
|
||
|
||
// использование анонимной функции
|
||
$result = ArrayHelper::index($array, function ($element) {
|
||
return $element['id'];
|
||
});
|
||
```
|
||
|
||
|
||
|
||
## Получение пар ключ-значение <span id="building-maps"></span>
|
||
|
||
Для получения пар ключ-значение из многомерного массива или из массива объектов вы можете использовать метод `map`.
|
||
|
||
Параметры `$from` и `$to` определяют имена ключей или свойств, которые будут использованы в map. Также третьим необязательным параметром вы можете задать правила группировки.
|
||
|
||
```php
|
||
$array = [
|
||
['id' => '123', 'name' => 'aaa', 'class' => 'x'],
|
||
['id' => '124', 'name' => 'bbb', 'class' => 'x'],
|
||
['id' => '345', 'name' => 'ccc', 'class' => 'y'],
|
||
);
|
||
|
||
$result = ArrayHelper::map($array, 'id', 'name');
|
||
// результат будет таким:
|
||
// [
|
||
// '123' => 'aaa',
|
||
// '124' => 'bbb',
|
||
// '345' => 'ccc',
|
||
// ]
|
||
|
||
$result = ArrayHelper::map($array, 'id', 'name', 'class');
|
||
// результат будет таким:
|
||
// [
|
||
// 'x' => [
|
||
// '123' => 'aaa',
|
||
// '124' => 'bbb',
|
||
// ],
|
||
// 'y' => [
|
||
// '345' => 'ccc',
|
||
// ],
|
||
// ]
|
||
```
|
||
|
||
|
||
## Многомерная сортировка <span id="multidimensional-sorting"></span>
|
||
|
||
Метод `multisort` помогает сортировать массивы объектов или вложенные массивы по одному или нескольким ключам. Например:
|
||
|
||
```php
|
||
$data = [
|
||
['age' => 30, 'name' => 'Alexander'],
|
||
['age' => 30, 'name' => 'Brian'],
|
||
['age' => 19, 'name' => 'Barney'],
|
||
];
|
||
ArrayHelper::multisort($data, ['age', 'name'], [SORT_ASC, SORT_DESC]);
|
||
```
|
||
|
||
После сортировки мы получим:
|
||
|
||
```php
|
||
[
|
||
['age' => 19, 'name' => 'Barney'],
|
||
['age' => 30, 'name' => 'Brian'],
|
||
['age' => 30, 'name' => 'Alexander'],
|
||
];
|
||
```
|
||
|
||
Второй аргумент, определяющий ключи для сортировки может быть строкой, если это один ключ, массивом, если используются несколько ключей или анонимной функцией, как в примере ниже:
|
||
|
||
```php
|
||
ArrayHelper::multisort($data, function($item) {
|
||
return isset($item['age']) ? ['age', 'name'] : 'name';
|
||
});
|
||
```
|
||
Третий аргумент определяет способ сортировки – от большего к меньшему или от меньшего к большему. В случае, если мы сортируем по одному ключу, передаем `SORT_ASC` или `SORT_DESC`. Если сортировка осуществляется по нескольким ключам, вы можете назначить направление сортировки для каждого из них с помощью массива.
|
||
|
||
Последний аргумент – это флаг, который используется в стандартной функции PHP `sort()`. Посмотреть его возможные значения можно [тут](https://www.php.net/manual/ru/function.sort.php).
|
||
|
||
|
||
## Определение типа массива <span id="detecting-array-types"></span>
|
||
|
||
Удобный способ для определения, является массив индексным или ассоциативным. Вот пример:
|
||
|
||
```php
|
||
// ключи не определены
|
||
$indexed = ['Qiang', 'Paul'];
|
||
echo ArrayHelper::isIndexed($indexed);
|
||
|
||
// все ключи - строки
|
||
$associative = ['framework' => 'Yii', 'version' => '2.0'];
|
||
echo ArrayHelper::isAssociative($associative);
|
||
```
|
||
|
||
|
||
## HTML-кодирование и HTML-декодирование значений <span id="html-encoding-values"></span>
|
||
|
||
|
||
Для того, чтобы закодировать или раскодировать специальные символы в массиве строк в HTML-сущности, вы можете пользоваться методами ниже:
|
||
|
||
```php
|
||
$encoded = ArrayHelper::htmlEncode($data);
|
||
$decoded = ArrayHelper::htmlDecode($data);
|
||
```
|
||
|
||
По умолчанию кодируются только значения. Если установить второй параметр в `false`, то ключи массива будут так же кодированы. Кодирование использует кодировку приложения, которая может быть изменена с помощью третьего аргумента.
|
||
|
||
## Слияние массивов <span id="merging-arrays"></span>
|
||
|
||
Слияние двух или больше массивов в один рекурсивно.
|
||
Если каждый массив имеет одинаковый ключ, последний будет перезаписывать предыдущий (в отличие от функции array_merge_recursive).
|
||
Рекурсивное слияние проводится когда все массивы имеют элемент одного и того же типа с одним и тем же ключом. Для элементов, ключом которого является значение типа integer, элементы из последнего будут добавлены к предыдущим массивам. Вы можете добавлять дополнительные массивы для слияния третьим, четвертым, пятым (и так далее) параметром.
|
||
|
||
```php
|
||
ArrayHelper::merge($a, $b);
|
||
```
|
||
|
||
## Получение массива из объекта <span id="converting-objects-to-arrays"></span>
|
||
|
||
Часто нужно конвертировать объект в массив. Наиболее распространенный случай – конвертация модели Active Record в массив.
|
||
|
||
```php
|
||
$posts = Post::find()->limit(10)->all();
|
||
$data = ArrayHelper::toArray($posts, [
|
||
'app\models\Post' => [
|
||
'id',
|
||
'title',
|
||
// ключ в результирующем массиве => имя свойства
|
||
'createTime' => 'created_at',
|
||
// ключ в результирующем массиве => анонимная функция
|
||
'length' => function ($post) {
|
||
return strlen($post->content);
|
||
},
|
||
],
|
||
]);
|
||
```
|
||
|
||
Первый аргумент содержит данные, которые вы хотите конвертировать. В нашем случае это модель Active Record `Post`.
|
||
|
||
Второй аргумент служит для управления процессом конвертации и может быть трех видов:
|
||
|
||
- просто имя поля
|
||
- пара ключ-значение, где ключ определяет ключ в результирующем массиве, а значение – название поля в модели, откуда берется значение.
|
||
- пара ключ-значение, где в качестве значения передается callback-функция, которая возвращает значение.
|
||
|
||
Результат конвертации будет таким:
|
||
|
||
```php
|
||
[
|
||
'id' => 123,
|
||
'title' => 'test',
|
||
'createTime' => '2013-01-01 12:00AM',
|
||
'length' => 301,
|
||
]
|
||
```
|
||
|
||
Вы можете определить способ конвертации из объекта в массив по-умолчанию реализовав интерфейс
|
||
[[yii\base\Arrayable|Arrayable]] в этом классе
|
||
|
||
|
||
## Проверка на присутствие в массиве <span id="testing-arrays"></span>
|
||
|
||
Часто необходимо проверить, содержится ли элемент в массиве, или является ли массив подмножеством другого массива.
|
||
К сожалению, PHP-функция `in_array()` не поддерживает подмножества объектов, реализующих интерфейс `\Traversable`.
|
||
|
||
Для таких случаев [[yii\helpers\ArrayHelper]] предоставляет [[yii\helpers\ArrayHelper::isIn()|isIn()]] и
|
||
[[yii\helpers\ArrayHelper::isSubset()|isSubset()]]. Методы принимают такие же параметры, что и
|
||
[in_array()](https://www.php.net/manual/ru/function.in-array.php).
|
||
|
||
```php
|
||
// true
|
||
ArrayHelper::isIn('a', ['a']);
|
||
// true
|
||
ArrayHelper::isIn('a', new(ArrayObject['a']));
|
||
|
||
// true
|
||
ArrayHelper::isSubset(new(ArrayObject['a', 'c']), new(ArrayObject['a', 'b', 'c'])
|
||
|
||
```
|