2

我在数据库中有一个包含类别数据的表:

id 标题 父级
1 类 1 0
2 类 2 2
3 类 3 3
4 类 4 0

每个父级都可能具有父级行 ID。

例如,类别 3 是类别 2 的子类别,类别 2 是类别 1 的子类别。

第一类
   第 2 类
      第 3 类

第 4 类

1 - 有没有更好的方法来操纵这种技术?2 - 我的实现是在一个 SQL 查询中获取所有行,然后使用递归函数来构建一个多维数组,然后我使用多级 foreach 遍历它来构建一个菜单或其他任何东西。我需要使用 PHP SPL 的更好方法。

我想创建一个完整的菜单或一个项目路径,如:

类别 1 -> 类别 2 -> 等等。

并创建一个网格,其中包含每行中的类别级别。

4

2 回答 2

3

如果您的数据是严格分层的,并且看起来确实如此,我建议您使用 Modified Preorder Tree Traversal 方法来存储您的数据。

Sitepoint上有一篇很棒的文章讨论了这个确切的问题。您似乎正在使用第一页讨论的邻接列表模型,但 MPTT 对于此类数据的大量读取存储更有效。

查看第 2 页以查看示例。这确实是一个非常优秀的建筑。

于 2009-05-08T03:20:28.853 回答
1

我最近使用单个查询和单个 while 循环完成了类似的操作。它使用引用通过平面结构(数组)构建树数据结构(数组)。没有涉及 SPL,因为我觉得没有必要。GitHub 上有一个更好的配色方案的要点 :)

/**
* Each element in the return array has a 'data' key, holding category data,
* like name, and a 'children' key holding its subcategories.
*
* @param resource $resource MySQL resource resulted from mysql_query
* @param string $id_key Name of the 'id' field
* @param string $parent_id_key Name of the 'parent_id' field
* @param boolean $use_cache Use cached result from previous calls. Defaults to TRUE
* @return array
*/
function categories($resource, $id_key, $parent_id_key, $use_cache = true) {
    // Cache the categories in a static local variable. This way, the query
    // will be executed just for the first function call. Subsequent calls
    // will return imediatelly, unless you tell it not to.
    static $tree = array();

    if ($tree && $use_cache) {
        return $tree;
    }

    // Flat representation of the categories for fast retrieval using array
    // keys. Each element will be referenced in the $tree array. This
    // allows to build a tree data structure using a flat one.
    $flat = array();

    // Reset the $tree, in case $use_cache=false in a subsequent call
    $tree = array();

    while ($row = mysql_fetch_object($resource)) {
        $flat[$row->$id_key] = array(
            'data' => $row,
            'children' => array(),
        );

        if (array_key_exists($row->$parent_id_key, $flat)) {
            // Assign children by reference so that possible subcategories of
            // this one will appear in the tree structure ($tree)
            $flat[$row->$parent_id_key]['children'][] =& $flat[$row->$id_key];
        }

        if ($row->$parent_id_key == 0) {
            // Assign by reference for synchronizing $flat with $tree;
            $tree[] =& $flat[$row->$id_key];
        }
    }

    return $tree;
}

此外,该功能与数据库的结构分离。您需要向它传递一个 mysql_query 资源、一个表示 id 字段的字符串和一个表示 parent_id 字段的字符串。不好的部分是它与 PHP mysql 扩展耦合,因为它使用对 mysql_fetch_object 的调用。它可能会得到改进。

其他一些优点是它会缓存后续调用的结果,除非您告诉它使缓存无效,这是第四个(布尔值)参数。

看看它是否对您有帮助。

于 2009-05-08T01:37:57.493 回答