mathishuettl's avatar

Category Tree

Hello,

I have a simple Category-Table with (ID, Title, parent) if it's a root category the parent is 0. Now I want to build a category tree with a dash (-) for each level like this:

Products
-Old Products
--Cheap Products
---...
----....
--Expensive Products
-New Products

How can i realize this?

0 likes
3 replies
spekkionu's avatar

There are two common ways of storing hierarchical data in a relational database.

The first an the one you are currently using is called an adjacency list. Here you store the id of the parent node in each record. With this method you need to rebuild the tree each time you need to use it which generally involve recursion and can be slow for larger trees. Caching is a must which also adds the complexity of cache invalidation.

The second method is called a nested set which is a bit more complex. I don't really know how to describe this method without diagrams so I'll just link to a good article that explains it.

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

The major benefit here is building the tree is much easier and faster. The downside is that adding, removing, or deleting a node requires rebuilding part of the tree and updating all the affected nodes.

There are two popular packages in laravel to allow for nested set eloquent models. Both are good and it really doesn't matter which one you use.

https://github.com/lazychaser/laravel-nestedset

http://etrepat.com/baum/

1 like
Sergiu17's avatar
Sergiu17
Best Answer
Level 60

@mathishuettl this is how I did.

// Categorie.php model

public function children()
{
    return $this->hasMany(Categorie::class, 'parent_id')->with('children');
}
// helper function to generate tree
function generateCategories($categories)
{
    foreach ($categories as $category) {
        echo '<li>' . $category->name . '</li>';
        if (count($category->children) > 0) {
            echo '<ul>';
                echo '<li>';
                    generateCategories($category->children);
                echo '</li>';
            echo '</ul>';
        }
    }
}
$categories = Categorie::where('parent_id', 0)->get();

<ul>
    generateCategories($categories);
</ul>
3 likes
Vilfago's avatar

You will have a lot of query on your database this way... nested set will be a better way I think

Please or to participate in this conversation.