Класс Set — повелитель массивов
Оказывается в недрах CakePHP давно живет класс Set, который активно используется в ядре и редко используется конечными пользователями. А между прочим зря.
Давайте-ка разберем типичную задачу. Предположим, мы получили список пользователей вот такого вида
$users = array
(
0 => array
(
'User' => array
(
'id' => 1
, 'name' => 'Вася'
)
)
, 1 => array
(
'User' => array
(
'id' => 2
, 'name' => 'Петя'
)
)
, 2 => array
(
'User' => array
(
'id' => 3
, 'name' => 'Акакий'
)
)
);
и допустим нам нужно получить только их имена, в виде массива. Как это делается обычно? Ну вот так
$userNames = array();
foreach ($users as $user)
{
$userNames[] = $user['User']['name'];
}
Казалось бы проще некуда. Но оказывается есть куда. Смотрите
$userNames = Set::extract($users, '{n}.User.name');
Не впечатляет? Тогда еще пример
$users = array
(
0 => array
(
'User' => array
(
'id' => 1
, 'name' => 'Вася'
, 'Item' => array
(
0 => array
(
'id' => 1
, 'name' => 'Холодильник'
)
, 1 => array
(
'id' => 2
, 'name' => 'Топор'
)
)
)
)
, 1 => array
(
'User' => array
(
'id' => 2
, 'name' => 'Петя'
, 'Item' => array
(
0 => array
(
'id' => 3
, 'name' => 'Машина'
)
)
)
)
, 2 => array
(
'User' => array
(
'id' => 3
, 'name' => 'Акакий'
, 'Item' => array
(
0 => array
(
'id' => 4
, 'name' => 'айфон'
)
, 1 => array
(
'id' => 5
, 'name' => 'плэйер'
)
, 2 => array
(
'id' => 6
, 'name' => 'мяч'
)
)
)
)
);
Предположим нам нужно получить из этого массив вида ‘User.name’ => ‘User.items’. Вот традиционный подход.
$userItems = array();
foreach ($users as $user)
{
foreach ($user['User']['Item'] as $item)
{
$userItems[$user['User']['name']][] = $item['name'];
}
}
а вот с помощью Set
$userItems = Set::combine($users, '{n}.User.name', '{n}.User.Item.{n}.name');
результатом в обоих случаях будет
Array
(
[Вася] => Array
(
[0] => Холодильник
[1] => Топор
)
[Петя] => Array
(
[0] => Машина
)
[Акакий] => Array
(
[0] => айфон
[1] => плэйер
[2] => мяч
)
)
На самом деле это лишь небольшая часть возможностей класса, в нем еще есть куча полезных методов. Set::merge — гибрид array_merge и array_merge_recursive (если элемент является массивом, то рекурсивная, если нет — то нет) Set::pushDiff — добавляет в конец первого массива разницу между ним и вторым массивом Set::extract — извлекает из массива информацию по XPath-селектору (‘/User/id’, например) Set::classicExtract — как и extract, только с классическими селекторами CakePHP (‘{n}.User.id’) Set::contains — есть ли в одном массиве ключи и значения из другого Set::diff — разница между двумя массивами Set::combine — создает из исходного массива ассоциированый с указанием ключей и значений (пример выше)