Spec-Zone.ru › Yii 2.0

ArrayHelper

  1. Получение значений
  2. Проверка существования ключей
  3. Извлечение столбцов
  4. Переиндексация массивов
  5. Создание словарей
  6. Многомерная сортировка
  7. Обнаружение типов массивов
  8. Кодирование и декодирование значений в HTML
  9. Объединение массивов
  10. Преобразование объектов в массивы
  11. Проверка массивов

В дополнение к широкому набору функций PHP для работы с массивами, помощник Yii для массивов предоставляет дополнительные статические методы, позволяющие более эффективно работать с массивами.

Получение значений

Извлечение значений из массива, объекта или сложной структуры, состоящей из обоих, с использованием стандартных функций PHP довольно повторяемо. Вам нужно сначала проверить, существует ли ключ с помощью isset, затем, если он существует, получить его, а если нет, предоставить значение по умолчанию:

class User
{
    public $name = 'Alex';
}

$array = [
    'foo' => [
        'bar' => new User(),
    ]
];

$value = isset($array['foo']['bar']->name) ? $array['foo']['bar']->name : null;

Yii предоставляет очень удобный метод для этого:

$value = ArrayHelper::getValue($array, 'foo.bar.name');

Первый аргумент метода указывает, откуда мы получаем значение. Второй аргумент определяет, как получить данные. Он может быть одним из следующих:

  • Имя ключа массива или свойства объекта для извлечения значения.
  • Набор ключей массива, разделенных точками, или имен свойств объекта. Тот, который мы использовали в примере выше.
  • Обратный вызов, возвращающий значение.

Обратный вызов должен быть следующим:

$fullName = ArrayHelper::getValue($user, function ($user, $defaultValue) {
    return $user->firstName . ' ' . $user->lastName;
});

Третий необязательный аргумент — это значение по умолчанию, которое равно null, если не указано. Может использоваться следующим образом:

$username = ArrayHelper::getValue($comment, 'user.username', 'Unknown');

Если вам нужно получить значение и сразу же удалить его из массива, вы можете использовать метод remove:

$array = ['type' => 'A', 'options' => [1, 2]];
$type = ArrayHelper::remove($array, 'type');

После выполнения кода $array будет содержать ['options' => [1, 2]], а $type будет A. Обратите внимание, что в отличие от метода getValue, метод remove поддерживает только простые имена ключей.

Проверка существования ключей

ArrayHelper::keyExists работает так же, как array_key_exists, за исключением того, что он также поддерживает сравнение ключей без учета регистра. Например,

$data1 = [
    'userName' => 'Alex',
];

$data2 = [
    'username' => 'Carsten',
];

if (!ArrayHelper::keyExists('username', $data1, false) || !ArrayHelper::keyExists('username', $data2, false)) {
    echo "Please provide username.";
}

Извлечение столбцов

Часто вам нужно получить столбец значений из массива строк данных или объектов. Типичный пример — получение списка идентификаторов.

$array = [
    ['id' => '123', 'data' => 'abc'],
    ['id' => '345', 'data' => 'def'],
];
$ids = ArrayHelper::getColumn($array, 'id');

Результат будет ['123', '345'].

Если требуется дополнительная обработка или способ получения значения сложный, второй аргумент можно указать как анонимную функцию:

$result = ArrayHelper::getColumn($array, function ($element) {
    return $element['id'];
});

Переиндексация массивов

Для индексации массива в соответствии с указанным ключом можно использовать метод index. Ввод должен быть либо многомерным массивом, либо массивом объектов. $key может быть именем ключа подмассива, именем свойства объекта или анонимной функцией, которая должна возвращать значение, которое будет использоваться в качестве ключа.

Атрибут $groups — это массив ключей, которые будут использоваться для группировки входного массива в один или несколько подмассивов на основе указанных ключей.

Если атрибут $key или его значение для конкретного элемента равно null, и $groups не определено, элемент массива будет отброшен. В противном случае, если $groups указан, элемент массива будет добавлен в результирующий массив без ключа.

Например:

$array = [
    ['id' => '123', 'data' => 'abc', 'device' => 'laptop'],
    ['id' => '345', 'data' => 'def', 'device' => 'tablet'],
    ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone'],
];
$result = ArrayHelper::index($array, 'id');

Результатом будет ассоциативный массив, где ключ — это значение атрибута id.

[
    '123' => ['id' => '123', 'data' => 'abc', 'device' => 'laptop'],
    '345' => ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone']
    // The second element of an original array is overwritten by the last element because of the same id
]

Анонимная функция, переданная в качестве $key, даёт тот же результат:

$result = ArrayHelper::index($array, function ($element) {
    return $element['id'];
});

Передача id в качестве третьего аргумента сгруппирует $array по id:

$result = ArrayHelper::index($array, null, 'id');

Результатом будет многомерный массив, сгруппированный по id на первом уровне и не индексированный на втором уровне:

[
    '123' => [
        ['id' => '123', 'data' => 'abc', 'device' => 'laptop']
    ],
    '345' => [ // all elements with this index are present in the result array
        ['id' => '345', 'data' => 'def', 'device' => 'tablet'],
        ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone'],
    ]
]

Анонимная функция может быть использована и в группирующем массиве:

$result = ArrayHelper::index($array, 'data', [function ($element) {
    return $element['id'];
}, 'device']);

Результатом будет многомерный массив, сгруппированный по id на первом уровне, по device на втором уровне и индексированный по data на третьем уровне:

[
    '123' => [
        'laptop' => [
            'abc' => ['id' => '123', 'data' => 'abc', 'device' => 'laptop']
        ]
    ],
    '345' => [
        'tablet' => [
            'def' => ['id' => '345', 'data' => 'def', 'device' => 'tablet']
        ],
        'smartphone' => [
            'hgi' => ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone']
        ]
    ]
]

Создание словарей

Для создания словаря (пар ключ-значение) из многомерного массива или массива объектов можно использовать метод map. Параметры $from и $to определяют имена ключей или имена свойств для создания словаря. Необязательно, можно дополнительно сгруппировать словарь по полю группировки $group. Например,

$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');
// the result is:
// [
//     '123' => 'aaa',
//     '124' => 'bbb',
//     '345' => 'ccc',
// ]

$result = ArrayHelper::map($array, 'id', 'name', 'class');
// the result is:
// [
//     'x' => [
//         '123' => 'aaa',
//         '124' => 'bbb',
//     ],
//     'y' => [
//         '345' => 'ccc',
//     ],
// ]

Многомерная сортировка

Метод multisort помогает сортировать массив объектов или вложенных массивов по одному или нескольким ключам. Например,

$data = [
    ['age' => 30, 'name' => 'Alexander'],
    ['age' => 30, 'name' => 'Brian'],
    ['age' => 19, 'name' => 'Barney'],
];
ArrayHelper::multisort($data, ['age', 'name'], [SORT_ASC, SORT_DESC]);

После сортировки мы получим следующее в $data:

[
    ['age' => 19, 'name' => 'Barney'],
    ['age' => 30, 'name' => 'Brian'],
    ['age' => 30, 'name' => 'Alexander'],
];

Второй аргумент, определяющий ключи для сортировки, может быть строкой, если это один ключ, массивом в случае нескольких ключей или анонимной функцией, как показано ниже:

ArrayHelper::multisort($data, function($item) {
    return isset($item['age']) ? ['age', 'name'] : 'name';
});

Третий аргумент — направление. В случае сортировки по одному ключу он может быть либо SORT_ASC, либо SORT_DESC. Если сортировка по нескольким значениям, вы можете сортировать каждое значение по-разному, указав массив направлений сортировки.

Последний аргумент — флаг сортировки PHP, который может принимать те же значения, что и те, которые передаются в функцию PHP sort().

Обнаружение типов массивов

Полезно знать, является ли массив индексированным или ассоциативным. Вот пример:

// no keys specified
$indexed = ['Qiang', 'Paul'];
echo ArrayHelper::isIndexed($indexed);

// all keys are strings
$associative = ['framework' => 'Yii', 'version' => '2.0'];
echo ArrayHelper::isAssociative($associative);

Кодирование и декодирование значений в HTML

Для кодирования или декодирования специальных символов в массиве строк в HTML-сущности можно использовать следующее:

$encoded = ArrayHelper::htmlEncode($data);
$decoded = ArrayHelper::htmlDecode($data);

По умолчанию кодируются только значения. Передав второй аргумент как false, вы также можете закодировать ключи массива. Кодирование будет использовать кодировку приложения и может быть изменено с помощью третьего аргумента.

Объединение массивов

Вы можете использовать ArrayHelper::merge() для рекурсивного объединения двух или более массивов в один. Если каждый массив имеет элемент с одинаковым строковым значением ключа, то последний перепишет предыдущий (в отличие от array_merge_recursive()). Рекурсивное объединение выполняется, если оба массива имеют элемент типа массив и имеют одинаковый ключ. Для элементов с целочисленными ключами элементы из последнего массива добавляются к первому массиву. Вы можете использовать объект yii\helpers\UnsetArrayValue для удаления значения из предыдущего массива или yii\helpers\ReplaceArrayValue для принудительной замены предыдущего значения вместо рекурсивного объединения.

Например:

$array1 = [
    'name' => 'Yii',
    'version' => '1.1',
    'ids' => [
        1,
    ],
    'validDomains' => [
        'example.com',
        'www.example.com',
    ],
    'emails' => [
        'admin' => 'admin@example.com',
        'dev' => 'dev@example.com',
    ],
];

$array2 = [
    'version' => '2.0',
    'ids' => [
        2,
    ],
    'validDomains' => new \yii\helpers\ReplaceArrayValue([
        'yiiframework.com',
        'www.yiiframework.com',
    ]),
    'emails' => [
        'dev' => new \yii\helpers\UnsetArrayValue(),
    ],
];

$result = ArrayHelper::merge($array1, $array2);

Результат будет:

[
    'name' => 'Yii',
    'version' => '2.0',
    'ids' => [
        1,
        2,
    ],
    'validDomains' => [
        'yiiframework.com',
        'www.yiiframework.com',
    ],
    'emails' => [
        'admin' => 'admin@example.com',
    ],
]

Преобразование объектов в массивы

Часто вам нужно преобразовать объект или массив объектов в массив. Наиболее распространенный случай — преобразование моделей активных записей для предоставления массивов данных через API REST или для другого использования. Следующий код может быть использован для этого:

$posts = Post::find()->limit(10)->all();
$data = ArrayHelper::toArray($posts, [
    'app\models\Post' => [
        'id',
        'title',
        // the key name in array result => property name
        'createTime' => 'created_at',
        // the key name in array result => anonymous function
        'length' => function ($post) {
            return strlen($post->content);
        },
    ],
]);

Первый аргумент содержит данные, которые мы хотим преобразовать. В нашем случае мы преобразуем модель Post AR.

Второй аргумент — отображение преобразования по классу. Мы устанавливаем отображение для модели Post. Каждый массив отображения содержит набор отображений. Каждое отображение может быть:

  • Имя поля для включения как есть.
  • Пара ключ-значение желаемого имени ключа массива и имени столбца модели, чтобы взять значение.
  • Пара ключ-значение желаемого имени ключа массива и обратного вызова, который возвращает значение.

Результат преобразования выше для одной модели будет:

[
    'id' => 123,
    'title' => 'test',
    'createTime' => '2013-01-01 12:00AM',
    'length' => 301,
]

Можно предоставить стандартный способ преобразования объекта в массив для определенного класса, реализовав интерфейс Arrayable в этом классе.

Проверка массивов

Часто необходимо проверить, является ли элемент частью массива или набор элементов является подмножеством другого. В то время как PHP предлагает in_array(), это не поддерживает подмножества или объекты \Traversable.

Для помощи в таких проверках, yii\helpers\ArrayHelper предоставляет isIn() и isSubset() с такой же сигнатурой, как in_array().

// true
ArrayHelper::isIn('a', ['a']);
// true
ArrayHelper::isIn('a', new ArrayObject(['a']));

// true 
ArrayHelper::isSubset(new ArrayObject(['a', 'c']), new ArrayObject(['a', 'b', 'c']));

© 2008–2017 by Yii Software LLC
Licensed under the three clause BSD license.
http://www.yiiframework.com/doc-2.0/guide-helper-array.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API