Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Proposal] Nested tree Flat to hierarchical array #4

Closed
Surt opened this issue May 27, 2013 · 3 comments
Closed

[Proposal] Nested tree Flat to hierarchical array #4

Surt opened this issue May 27, 2013 · 3 comments

Comments

@Surt
Copy link
Contributor

Surt commented May 27, 2013

Would be good to have this addition somewhere. Maybe in the collection returned? I didn't examine closely a way to override the Collection sets in Eloquent.

It takes a flat array with all the tree and converts it in a hierarchical array. I setted a path specifically for my models, it would be better having the option to specify a path settings or something.

I took it from: http://www.sitepoint.com/forums/showthread.php?143727-Converting-Nested-Set-Array-into-a-Nested-Array

       function nestedArray(&$result, $right = 'rgh', $left = 'lft', $path = '', $level = -1) {
            $new = array();
            if(is_array($result)) {
                while(list($n, $sub) = each($result)) {
                    $subId = $sub['id'];
                    $new[$subId] = $sub;
                    $alias = (isset($sub['data']))?$sub['data']['alias']:'';
                    $new[$subId]['_tree_path'] = $path.'/'.$alias;
                    $new[$subId]['_tree_level'] = $level + 1;

                    if($sub[$right] - $sub[$left] != 1) {
                        // recurse ($result is manipulated by reference!)
                        $new[$subId]['children'] = nestedArray($result, $right, $left, $new[$subId]['_tree_path'], $new[$subId]['_tree_level']);
                    }

                    $next_id = key($result);
                    if($next_id && $result[$next_id]['parent_id'] != $sub['parent_id']) {
                        return $new;
                    }
                }
            }
            return $new;
        }
@Surt
Copy link
Contributor Author

Surt commented May 28, 2013

I think I have it.

new Collection.php inside baum.

<?php
namespace Baum;

use Illuminate\Database\Eloquent\Collection as Eloquent_Collection;

class Collection extends Eloquent_Collection {

    private function nestedArray(&$result, $right = 'rgh', $left = 'lft', $path = '', $level = -1) {
        $new = array();
        if(is_array($result)) {
            while(list($n, $sub) = each($result)) {
                $subId = $sub['id'];
                $new[$subId] = $sub;
                $alias = (isset($sub['data']))?$sub['data']['alias']:'';
                $new[$subId]['_tree_path'] = $path.'/'.$alias;
                $new[$subId]['_tree_level'] = $level + 1;

                if($sub[$right] - $sub[$left] != 1) {
                    // recurse ($result is manipulated by reference!)
                    $new[$subId]['children'] = $this->nestedArray($result, $right, $left, $new[$subId]['_tree_path'], $new[$subId]['_tree_level']);
                }

                $next_id = key($result);
                if($next_id && $result[$next_id]['parent_id'] != $sub['parent_id']) {
                    return $new;
                }
            }
        }
        return $new;
    }

    public function toHierarchical(){
        $tree = $this->toArray();
        return $this->nestedArray($tree);
    }
}

and, at Baum\Node.php add a new method

    public function newCollection(array $models = array())
    {
        return new Baum\Collection($models);
    }

It needs some tweaks, using getQualifiedLeftColumName, etc... and adding the changes to make path as option, etc...
I will try to make the changes when I get some time. (If nobody makes it before)

@Surt
Copy link
Contributor Author

Surt commented May 28, 2013

Done...
The "toHierarchical" method returns a Eloquent\Collection of models, each element with its children in a hierarchical way.

Now is possible to do a $collection->toHierarchical()->toArray(); if needed.

<?php
namespace Baum;

use Illuminate\Database\Eloquent\Collection as Eloquent_Collection;

class Collection extends Eloquent_Collection {

    public function toHierarchical(){
        $tree = $this->items;
        return new Eloquent_Collection($this->hierarchical($tree));
    }


    private function hierarchical(&$result) {
        $new = array();
        if(is_array($result)) {
            while(list($n, $sub) = each($result)) {
                $new[$sub->getKey()] = $sub;
                if($sub->getRight() - $sub->getLeft() != 1) {
                    $new[$sub->getKey()]->children = $this->hierarchical($result);
                }
                $next_id = key($result);
                if($next_id && $result[$next_id]->getParentId() != $sub->getParentId()) {
                    return $new;
                }
            }
        }
        return $new;
    }
}

@etrepat
Copy link
Owner

etrepat commented Jul 3, 2013

As we are using #5 to discuss and you've provided the implementation, I'm closing this issue...

@etrepat etrepat closed this as completed Jul 3, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants