在PHP中使用数组而不是大量的数据库查询

问题描述 投票:2回答:4

我的功能看起来像那样。它工作但很多工作(递归调用自己并执行大量的数据库查询)。必须有另一种方法来做同样的事情,但使用数组(有一个查询)。我无法弄清楚如何修改此函数以使其与数组一起使用。

function genMenu($parent, $level, $menu, $utype) {
    global $db;
    $stmt=$db->prepare("select id, name FROM navigation WHERE parent = ? AND menu=? AND user_type=?") or die($db->error);
    $stmt->bind_param("iii", $parent, $menu, $utype) or die($stmt->error);
    $stmt->execute() or die($stmt->error);

    $stmt->store_result();
    /* bind variables to prepared statement */
$stmt->bind_result($id, $name) or die($stmt->error);
    if ($level > 0 && $stmt->num_rows > 0) {
        echo "\n<ul>\n";
    }
    while ($stmt->fetch()) {
        echo "<li>";
        echo '<a href="?page=' . $id . '">' . $name . '</a>';
        //display this level's children
        genMenu($id, $level+1, $menu, $utype);
        echo "</li>\n\n";
    }
    if ($level > 0 && $stmt->num_rows > 0) {
        echo "</ul>\n";
    }
    $stmt->close();
}
php mysql mysqli prepared-statement
4个回答
2
投票

你可以很容易地构建一个基于树的数组,所以它是一个单一的查询,然后是一堆PHP逻辑来进行数组构建:

$tree = array();
$sql = "SELECT id, parent, name FROM menu WHERE parent ... etc.... ";
$results = mysql_query($sql) or die(mysql_error());
while(list($id, $parent, $name) = mysql_fetch_assoc($results)) {
    $tree[$id] = array('name' => $name, 'children' => array(), 'parent' => $parent);
    if (!array_key_exists($tree[$parent]['children'][$id])) {
        $tree[$parent]['children'][$id] = $id;
    }
}

为此,我假设您的树有一个顶级'0'节点。如果没有,那么你将不得不调整一下。

这将为您提供双链接树结构。树中的每个节点都有一个['children']子数组中的子节点列表,树中的每个节点也通过['parent']属性指向其父节点。

给定一个起始节点,您可以像这样遍历树:

$cur_node = 57; // random number
$path = array();
do {
    $parent = $tree[$cur_node]['parent'];
    $path[] = $parent;
    $cur_node = $parent;
} while ($parent != 0);

1
投票

我认为你可以解决的第一件事就是删除WHERE parent =?子句然后处理生成的查询结果,这将使您在管理结果方面工作更多,但肯定会保护您的IO操作。

使用Marc B Solution的部分内容

$tree = array();
$sql = "select id, parent, name FROM navigation AND menu=? AND user_type=?";
$results = mysql_query($sql) or die(mysql_error());
while(list($id, $parent, $name) = mysql_fetch_assoc($results)) {
    $tree[$id] = array('name' => $name, 'children' => array(), 'parent' => $parent);
    if (!array_key_exists($tree[$parent]['children'][$id])) {
        $tree[$parent]['children'][$id] = $id;
    }
}

print_r($tree);

更换 ?用实际值,并给出一个运行,你的输出是什么?


1
投票

也许不是你想要的,但是对于trees来说它很棒。你必须重建你的表并有一些代码输出html,但你只有一个查询。从长远来看,这可能是值得的。

即,如果你有这个菜单

# Menu hierarchy:
 - Home
 - Product
    |- Tv
    |- Radio
 - About us   

它在db中看起来像这样。

+----+----------+-----------+-----+-----+
| id | menu     | parent_id | lft | rgt |
+----+----------+-----------+-----+-----+
| 1  | Home     | null      | 1   | 2   |
+----+----------+-----------+-----+-----+
| 2  | Product  | null      | 3   | 8   |
+----+----------+-----------+-----+-----+
| 3  | Tv       | 2         | 4   | 5   |
+----+----------+-----------+-----+-----+
| 4  | Radio    | 2         | 6   | 7   |
+----+----------+-----------+-----+-----+
| 5  | About us | null      | 9   | 10  |
+----+----------+-----------+-----+-----+

可以使用类似的查询来获取数据

$select = "SELECT * FROM table_name WHERE lft BETWEEN 3 AND 8;"

要输出特定菜单:

 - Product
    |- Tv
    |- Radio

我知道它不是你正在寻找的答案,但仅供参考,还有其他方法可以使用分层树数据。

祝好运。


0
投票

我过去用丑陋的方式编写了一些简单的SELECT:

我存储在text / varchar字段字符串中,如下所示:

/001
/001/001
/001/002
/002
/002/001
/002/001/001

忽略希伯来语并查看window.aMessages数组,看看它是如何工作的:http://www.inn.co.il/Forum/Forum.aspx/t394009#4715854

© www.soinside.com 2019 - 2024. All rights reserved.