我在数据库中有一个表,其中包含类别数据:
id title parent 1 category 1 0 2 category 2 2 3 category 3 3 4 category 4 0
Eeach父级可能拥有父行ID。
例如,类别3是类别2的子级,属于类别1的子级。
category 1 category 2 category 3 category 4
1 - 有没有更好的方法来操纵这种技术? 2 - 我的实现是获取一个SQL查询中的所有行,然后使用递归函数构建一个多维数组,然后我使用多级foreach循环它来构建菜单或其他任何东西。我需要一种更好的方法来使用PHP SPL。
我想要创建完整菜单或项目路径,如:
category1 -> catgory 2 -> etc.
并创建一个网格,其中包含每行中的类别级别。
答案 0 :(得分:3)
如果您的数据是严格分层的,并且它看起来像是,我建议使用Modified Preorder Tree Traversal方法来存储您的数据。
有一个superb article at Sitepoint讨论了这个确切的问题。您似乎正在使用第1页讨论的Adjacency List模型,但MPTT对于此类数据的大量存储更有效。
查看page 2以查看示例。这是一个非常优秀的建筑。
答案 1 :(得分:1)
我最近使用单个查询和单个while循环来完成类似的操作。它使用引用通过平面(数组)构建树数据结构(数组)。没有涉及SPL,因为我觉得不需要它。有a gist on 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的调用。它可能会得到改善。
其他一些优点是它会为后续调用缓存结果,除非你告诉它使缓存无效,这是第四个(布尔)参数。
看看它是否对你有帮助。