简体   繁体   English

此PHP递归函数有什么问题?

[英]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. 我的测试/调试已确认,在将mensvests作为categoryId传递到函数后,下一个传递的categoryId是women,应定位最后一个子猫。 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? 如果您有50个不同的类别分支,您是否真的要运行50个左右的查询,只是为了显示它们? You should read this article on managing hierarchical data with MySQL. 您应该阅读有关使用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. 退出停止整个程序,而return(即使您不给tu赋值)也可以退出该函数。

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. 对我来说,最好的方法是首先获取所有结果(使用mysqli_fetch_all ),然后以允许您以正确顺序显示它的方式对数组进行排序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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