laravel-nestedset icon indicating copy to clipboard operation
laravel-nestedset copied to clipboard

generate inverse tree from leaf and output it as JSON

Open scramatte opened this issue 5 years ago • 2 comments

hi,

I need to render as JSON inverse tree from specific node

My tree must includes:

  • children of the node itself
  • ancestors with their sibling leaves grouped
  • exclude root

What I've done:

$traverse = function ($nodes, $prefix = '-') use (&$traverse) {
    foreach ($nodes as $node) {
        echo PHP_EOL.$prefix.' '.$node->handle .'(L:' .$node->left. ';R:'. $node->right .')';
        $traverse($node->children, $prefix.'-');
    }
};

$rootId = ItemAttribute::whereIsRoot()->get()->first()->id;

$node =  ItemAttribute::descendantsAndSelf(27);
$nodes = $node;

$ancestors = $node->find(27)->getAncestors();

foreach ($ancestors as $ancestor) {
   $nodes = $nodes->merge($ancestor->siblings()->whereIsLeaf()->get());
}

$nodes = $nodes->merge($ancestors);
$tree = $nodes->toTree($rootId);

echo '<pre>';
$traverse($tree);

My output data are fine except that is not ordered properly: "test" should be above "display_name".

- default_fields(L:2;R:15)
-- display_name(L:13;R:14)
-- test(L:3;R:4)
-- network(L:5;R:12)
--- router(L:6;R:11)
---- serialnumber(L:7;R:8)
---- macaddress(L:9;R:10)

Moreover I need to group ancestors leafs together, I mean that "display_name" node must not appears at end despite of it's left/right values.

My database values

image

Finally I need to tune $traverse function to generate JSON output. Can you give me an hand?

Regards

scramatte avatar May 18 '20 22:05 scramatte

Sorry for noise, I answer to myself. defaultOrder need to be called on the query.

foreach ($ancestors as $ancestor) {
   $nodes = $nodes->merge($ancestor->siblings()->defaultOrder()->whereIsLeaf()->get());
}
- default_fields(L:2;R:15)
-- test(L:3;R:4)
-- display_name(L:13;R:14)
-- network(L:5;R:12)
--- router(L:6;R:11)
---- serialnumber(L:7;R:8)
---- macaddress(L:9;R:10)

So now I only need to output it a JSON.

scramatte avatar May 18 '20 22:05 scramatte

you can also add to your model

/**
     * Get query ancestors of the node.
     *
     * @return AncestorsRelation
     */
    public function ancestors()
    {
        return new AncestorsRelation($this->newQuery()->defaultOrder(), $this);
    }

    /**
     * Get query for descendants of the node.
     *
     * @return DescendantsRelation
     */
    public function descendants()
    {
        return new DescendantsRelation($this->newQuery()->defaultOrder(), $this);
    }

ctf0 avatar Jul 23 '20 18:07 ctf0