简体   繁体   English

PHP SPL操作递归菜单

[英]PHP SPL to manipulate recursive menu

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. 每个父级可以具有父级行ID。

For example, category 3 is a child of category 2, which is child of category 1. 例如,类别3是类别2的子级,它是类别1的子级。

category 1
   category 2
      category 3

category 4

1 - Is there a better way to manipulate this technique? 1-是否有更好的方法来操纵此技术? 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. 2-我的实现是在一个SQL查询中获取所有行,然后使用递归函数构建多维数组,然后使用多级foreach遍历该数组以构建菜单或其他内容。 I need a better way using PHP SPL. 我需要使用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. 并创建一个在每一行中包含类别级别的网格。

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. Sitepoint上有一篇很棒的文章讨论了这个确切的问题。 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. 您似乎正在使用邻接表模型,该模型在第1页上进行了讨论,但是MPTT对于此类数据的大量读取存储效率更高。

Check out page 2 to see the examples. 请查看第2页以查看示例。 It's really quite an excellent piece of architecture. 这确实是一个很棒的架构。

I've recently dome something similar using a single query and a single while loop. 我最近使用一个查询和一个while循环为类似的东西做圆顶。 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. 没有涉及SPL,因为我认为没有必要。 There's a gist on GitHub with a better color scheme :) 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;
}

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. 您需要向其传递mysql_query资源,代表id字段的字符串和代表parent_id字段的字符串。 The bad part is that it is coupled to the PHP mysql extension because it uses a call to mysql_fetch_object. 缺点是它与PHP mysql扩展耦合,因为它使用对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. 看看它是否对您有帮助。

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

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