PHP tree structure for categories and sub categories without looping a query

后端 未结 4 1585
猫巷女王i
猫巷女王i 2020-12-02 05:16

I\'m trying to create a list of categories with any number of sub categories, where sub categories can also has their own sub categories.

I have selected all categor

4条回答
  •  無奈伤痛
    2020-12-02 05:35

    I had the same problem and solved it this way: fetch cat rows from DB and for each root categories, build tree, starting with level (depth) 0. May not be the most efficient solution, but works for me.

    $globalTree = array();
    $fp = fopen("/tmp/taxonomy.csv", "w");
    
    // I get categories from command line, but if you want all, you can fetch from table
    $categories = $db->fetchCol("SELECT id FROM categories WHERE parentid = '0'");
    
    foreach ($categories as $category) {
        buildTree($category, 0);
        printTree($category);
        $globalTree = array();
    }
    
    fclose($file);
    
    function buildTree($categoryId, $level)
    {
        global $db, $globalTree;
        $rootNode = $db->fetchRow("SELECT id, name FROM categories WHERE id=?", $categoryId);
        $childNodes = $db->fetchAll("SELECT * FROM categories WHERE parentid = ? AND id <> ? ORDER BY id", array($rootNode['id'], $rootNode['id']));
        if(count($childNodes) < 1) {
            return 0;
        } else {
            $childLvl = $level + 1;
            foreach ($childNodes as $childNode) {
                $id = $childNode['id'];
                $childLevel = isset($globalTree[$id])? max($globalTree[$id]['depth'], $level): $level;
                $globalTree[$id] = array_merge($childNode, array('depth' => $childLevel));
                buildTree($id, $childLvl);
            }
        }
    }
    
    function printTree($categoryId) {
        global $globalTree, $fp, $db;
        $rootNode = $db->fetchRow("SELECT id, name FROM categories WHERE id=?", $categoryId);
        fwrite($fp, $rootNode['id'] . " : " . $rootNode['name'] . "\n");
        foreach ($globalTree as $node) {
            for ($i=0; $i <= $node['depth']; $i++) {
                fwrite($fp, ",");
            }
            fwrite($fp, $node['id'] " : " . $node['name'] . "\n");
        }
    }
    

    ps. I am aware that OP is looking for a solution without DB queries, but this one involves recursion and will help anybody who stumbled across this question searching for recursive solution for this type of question and does not mind DB queries.

提交回复
热议问题