简体   繁体   中英

What's wrong with this PHP Recursive Function?

I have a database table with the following data:

categoryId    categoryName    parentCategory
men           Men             root
women         Women           root
shoes         Shoes           root
mensshirts    Men's Shirts    men
menspants     Men's Pants     men
mensjeans     Men's Jeans     men
mensvests     Men's Vests     men
womensshirts  Women's Shirts  women
womenpants    Women's Pants   women

I'm using a recursive function to print out a tiered menu. The code is below.

function display_children($parent) {
    global $connect;
    $query = "SELECT categoryId, categoryName FROM categories WHERE parentCategory='$parent'";
    $result = mysqli_query($connect,$query);

    if ( $result === false ) {
       printf("Query Error: %s\n", mysqli_error($connect));
       exit();
    }

    echo "<ul>";
    while ($row = mysqli_fetch_assoc($result)) {
       extract($row);
       echo "<li>".$categoryName."</li>";
       display_children($categoryId);   
    }
    echo "</ul>";

    mysqli_close($connect);
}

display_children('root');

As a result, I get this printed out on screen:

  • Men
    • Men's Shirts
    • Men's Pants
    • Men's Jeans
    • Men's Vests
  • Women
  • Shoes

The recursive function is not printing out the rest of the subcats, and I'm not sure why. My testing/debugging has confirmed that after mensvests is passed as a categoryId into the function, the next categoryId passed is women, which should locate the last subcats. Any ideas?

Honestly, you should reevaluate your approach to this and scrap the function. Running queries in a recursive function is just looking for trouble. If you have 50 different branches of categories, do you really want to run 50 or so queries, just to display them? You should read this article on managing hierarchical data with MySQL. By using the right approach, you can run one query instead of multiple queries. Example from the article that would apply to your scenario:

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id

It's worth noting that the article actually recommends following a Nested Set Model.

You are closing the DB connection at the end of the function. For recursive iterations, you will not have a connection to use after the first recursion goes to full depth.

A better approach would be to pass your db connection into the function as a parameter

function display_children($parent, $db) {
    // when you recurse call
    display_children($categoryId, $db);
}

display_children('root', $connect);
mysqli_close($connect);

I think your problem is in the fact you use "exit" instead of "return" statement. Moreover you close your connection with

mysqli_close($connect);

It is not what you want to do. Exit stop your whole program whereas return (even if you do not give a value tu return) just go out the function.

Then you have to change your algorithm, it is totaly not the right way to do this.

For me, the best way to do it is to first fetch all results (using mysqli_fetch_all ) and then sort your array in a way that allows you to display it in the right order.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM