PHP SPL 操作递归菜单

发布于 2024-07-19 02:45:09 字数 519 浏览 3 评论 0原文

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

id   title       parent 
1    category 1  0
2    category 2  2
3    category 3  3
4    category 4  0

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

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

category 1
   category 2
      category 3

category 4

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

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

category1 -> catgory 2 -> etc.

并创建一个网格来保存每行中的类别级别。

I have a table in a database which has category data:

id   title       parent 
1    category 1  0
2    category 2  2
3    category 3  3
4    category 4  0

Eeach parent may have the parent row id.

For example, category 3 is a child of category 2, which is child of category 1.

category 1
   category 2
      category 3

category 4

1 - Is there a better way to manipulate this technique?
2 - My implementation is to fetch all the rows in one SQL query, then use a recursive function to build a multi-dimensional array, then I loop through it using multi level foreach to build a menu or whatever. I need a better way using PHP SPL.

I want to create either a full menu or an item path like:

category1 -> catgory 2 -> etc.

and create a grid which holds the category level in each row.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

埖埖迣鎅 2024-07-26 02:45:09

如果您的数据是严格分层的(而且看起来确实如此),我会推荐使用修改的预序树遍历方法来存储数据。

Sitepoint 有一篇精彩文章讨论了这个确切的问题。 您似乎正在使用邻接列表模型,该模型已在第一页中讨论,但 MPTT 对于此类数据的读取密集型存储要高效得多。

请查看第 2 页查看示例。 这确实是一件非常出色的建筑。

If your data is strictly hierarchical, and it looks like it is, I would recommend the Modified Preorder Tree Traversal method for storing your data.

There is a superb article at Sitepoint that discusses this exact problem. You appear to be using the Adjacency List model, which is discussed on page one, but the MPTT is much more efficient for a read-heavy storage of this type of data.

Check out page 2 to see the examples. It's really quite an excellent piece of architecture.

倾其所爱 2024-07-26 02:45:09

我最近使用单个查询和单个 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 的调用。 它可能可以改进。

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

看看对你是否有帮助。

I've recently dome something similar using a single query and a single while loop. It uses references to build a tree data structures (array) by means of a flat one (array). There's no SPL involved because I don't felt there was a need for it. There's a gist on GitHub with a better color scheme :)

/**
* 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;
}

Also, the function is decoupled from the structure of the database. You need to pass it a mysql_query resource, a string representing the id field and a string representing the parent_id field. The bad part is that it is coupled to the PHP mysql extension because it uses a call to mysql_fetch_object. It could probably be improved.

Some other advantage is that it caches the result for consequent calls, unless you tell it to invalidate the cache, which is the fourth (boolean) parameter.

Take a look and see if it helps you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文