recursive function to get all the child categories

2019-01-11 11:37发布

Here is what I'm trying to do: - i need a function that when passed as an argument an ID (for a category of things) will provide all the subcategories and the sub-sub categories and sub-sub-sub..etc. - i was thinking to use a recursive function since i don't know the number of subcategories their sub-subcategories and so on so here is what i've tried to do so far

function categoryChild($id) {

    $s = "SELECT * FROM PLD_CATEGORY WHERE PARENT_ID = $id";
    $r = mysql_query($s);

    if(mysql_num_rows($r) > 0) {

        while($row = mysql_fetch_array($r))
            echo $row['ID'].",".categoryChild($row['ID']);
    }
    else {
        $row = mysql_fetch_array($r);
        return $row['ID'];
    }
}

If i use return instead of echo, i won't get the same result. I need some help in order to fix this or rewrite it from scratch

7条回答
甜甜的少女心
2楼-- · 2019-01-11 12:17

As this has been brought up by @Pawan Sharma, I thought that I might give some answer as well.

All given solutions suffer from common problem - they perform SQL query for each and every child. E.g., if there are 100 childs in 2nd level, then 100 queries will be done, while it can actually be done in single query by using where parent_id in (<list_of_ids>).


Sample DB:

create table category (
    id          int auto_increment primary key,
    parent_id   int default null,
    title       tinytext,
    foreign key (parent_id) references category (id)
) engine = InnoDB;

insert into category (id, parent_id, title) values
    (1, null, '1'),
    (2, null, '2'),
    (3, null, '3'),
    (4, 1   , '1.1'),
    (5, 1   , '1.2'),
    (6, 1   , '1.3'),
    (7, 4   , '1.1.1'),
    (8, 4   , '1.1.2'),
    (9, 7   , '1.1.1.1');

Here's my solution:

/**
 * @param null|int|array $parentID
 */
function getTree($parentID) {
    $sql = "select id, parent_id, title from category where ";
    if ( is_null($parentID) ) {
        $sql .= "parent_id is null";
    }
    elseif ( is_array($parentID) ) {
        $parentID = implode(',', $parentID);
        $sql .= "parent_id in ({$parentID})";
    }
    else {
        $sql .= "parent_id = {$parentID}";
    }

    $tree = array();
    $idList = array();

    $res = mysql_query($sql);
    while ( $row = mysql_fetch_assoc($res) ) {
        $row['children'] = array();
        $tree[$row['id']] = $row;
        $idList[] = $row['id'];
    }
    mysql_free_result($res);

    if ( $idList ) {
        $children = getTree($idList);
        foreach ( $children as $child ) {
            $tree[$child['parent_id']]['children'][] = $child;
        }
    }
    return $tree;
}

With provided sample data, it does at most 5 queries, when called as getTree(null) (for all entries):

select id, parent_id, title from category where parent_id is null
select id, parent_id, title from category where parent_id in (1,2,3)
select id, parent_id, title from category where parent_id in (4,5,6)
select id, parent_id, title from category where parent_id in (7,8)
select id, parent_id, title from category where parent_id in (9)

When called as getTree(4), 3 queries are performed:

select id, parent_id, title from category where parent_id = 4
select id, parent_id, title from category where parent_id in (7,8)
select id, parent_id, title from category where parent_id in (9)
查看更多
登录 后发表回答