Skip to content

Instantly share code, notes, and snippets.

@wajdijurry
Last active November 17, 2018 11:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wajdijurry/303075f2da6b4d0677ea3dffafe85991 to your computer and use it in GitHub Desktop.
Save wajdijurry/303075f2da6b4d0677ea3dffafe85991 to your computer and use it in GitHub Desktop.
Convert one-dimensional array to tree (parent -> children)
<?php
/**
* Author:Wajdi Jurry <jurrywajdi@yahoo.com> (https://github.com/wajdijurry)
* Requires PHP >= 5
*/
class ArrayHelper
{
private $parentIdAttribute;
private $itemIdAttribute;
private $subItemsSlug;
private $noParentValue;
private $array;
public function __construct(array $array, array $params)
{
$this->array = $array;
$this->itemIdAttribute = $params['itemIdAttribute'];
$this->parentIdAttribute = $params['parentIdAttribute'];
$this->subItemsSlug = $params['subItemsSlug'];
$this->noParentValue = $params['noParentValue'];
}
/**
* Creating multidimensional array from one-dimensional array, based on itemId and parentId
* @return array
* @throws \Exception
*/
public function prepare()
{
$ids = array_column($this->array, $this->itemIdAttribute);
foreach ($this->array as $key => &$value) {
if ($value[$this->parentIdAttribute] != $this->noParentValue) {
$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($this->array), \RecursiveIteratorIterator::CHILD_FIRST);
while ($iterator->valid()) {
if ($iterator->key() == $this->itemIdAttribute && $iterator->current() == $value[$this->parentIdAttribute]) {
$iterator->offsetSet($this->subItemsSlug, array_merge((array)$iterator->offsetGet($this->subItemsSlug), [$value]));
$current = (array) $iterator->getSubIterator($iterator->getDepth());
for ($i = $iterator->getDepth()-1; $i > 0; $i--) {
$parents = (array) $iterator->getSubIterator($i);
if (array_key_exists($this->subItemsSlug, $parents)) {
$parents[$this->subItemsSlug] = $current;
} else {
$parentItemsIndexes = array_column($parents, $this->itemIdAttribute);
$parentIndex = array_search($current[$this->itemIdAttribute], $parentItemsIndexes);
$parents[$parentIndex] = $current;
}
$current = $parents;
}
$this->array[array_search($current[$this->itemIdAttribute], $ids)] = $current;
unset($this->array[$key]);
break;
}
$iterator->next();
}
}
}
return array_values($this->array);
}
}
//Examples:
$items = [
['itemId' => 'Men', 'parentId' => null],
['itemId' => 'TopsMen', 'parentId' => 'Men'],
['itemId' => 'BottomsMen', 'parentId' => 'Men'],
['itemId' => 'JacketsMen', 'parentId' => 'TopsMen'],
['itemId' => 'BlazersMen', 'parentId' => 'TopsMen'],
['itemId' => 'JeansMen', 'parentId' => 'BottomsMen'],
['itemId' => 'ShoesMen', 'parentId' => 'BottomsMen'],
['itemId' => 'TrainingMen', 'parentId' => 'TopsMen'],
['itemId' => 'Women', 'parentId' => null],
['itemId' => 'TopsWomen', 'parentId' => 'Women'],
['itemId' => 'BottomsWomen', 'parentId' => 'Women'],
['itemId' => 'JacketsWomen', 'parentId' => 'BottomsWomen'],
['itemId' => 'BlazersWomen', 'parentId' => 'TopsWomen'],
['itemId' => 'JeansWomen', 'parentId' => 'BottomsWomen'],
['itemId' => 'ShoesWomen', 'parentId' => 'BottomsWomen'],
['itemId' => 'TrainingWomen', 'parentId' => 'TopsWomen']
];
$ah = new ArrayHelper($items, [
'itemIdAttribute' => 'itemId',
'parentIdAttribute' => 'parentId',
'subItemsSlug' => 'children',
'noParentValue' => null
]);
print_r($ah->prepare());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment