我有一个描述层次结构的db表。这是结构
id | pid | uid
1 5 2
2 2 3
3 2 4
4 2 6
5 3 7
在树形结构中它会看起来像这样。这只是一个例子,它们可能是更多的节点。
2
/ | \
3 4 6
/
7
所以在php和mysql中我获取所有数据并将其保存到数组中。
我想遍历该数组以确定例如特定级别的id的数量,我希望能够从一个级别检索所有节点。
我怎么能在PHP中这样做?
修改
这就是我创建数组的方式:
foreach ( $resultSet as $row ) {
$entry = array();
$entry['id'] = $row->id;
$entry['uid'] = $row->uid;
$entry['rid'] = $row->rid;
$entry['date'] = $row->date;
$entries [] = $entry;
}
这就是我现在使用答案
创建树的方法$tree = array();
foreach($entries as $key){
$this->adj_tree($tree, $key);
}
return $tree;
但是当我打印$ tree
时,我得到一些奇怪的输出Array ( [24] => Array ( [id] => 6 [uid] => 24 [rid] => 83 [date] => 2011-06-15
17:54:14 ) [] => Array ( [_children] => Array ( [0] => Array ( [id] => 6 [uid] => 24
[rid] => 83 [date] => 2011-06-15 17:54:14 ) [1] => Array ( [id] => 6 [uid] => 24 [rid] =>
83 [date] => 2011-06-15 17:54:14 ) ) ) )
但实际上应该有一个父母的uid为24,其中两个孩子有82和83
答案 0 :(得分:4)
你没有说你是如何使用你的桌子的,但我想这是一个商店类别树,或类似的东西,即一个不需要任何复杂存储的小数据集。您可以立即读取整个表格并使用php动态构建树形结构。它就像这样
function adj_tree(&$tree, $item) {
$i = $item['uid'];
$p = $item['pid'];
$tree[$i] = isset($tree[$i]) ? $item + $tree[$i] : $item;
$tree[$p]['_children'][] = &$tree[$i];
}
示例:
$tree = array();
$rs = my_query("SELECT * FROM categories");
while($row = my_fetch($rs))
adj_tree($tree, $row);
最后,你得到一个项目数组,每个项目包含'_children'子数组,而这些子数组又包含对其他项的引用(或为空)。
完整示例,包含问题数据
$entries = array(
array('id' => 1, 'pid' => 5, 'uid' => 2),
array('id' => 2, 'pid' => 2, 'uid' => 3),
array('id' => 3, 'pid' => 2, 'uid' => 4),
array('id' => 4, 'pid' => 2, 'uid' => 6),
array('id' => 5, 'pid' => 3, 'uid' => 7),
);
$tree = array();
foreach($entries as $row)
adj_tree($tree, $row);
function print_tree($node, $indent) {
echo str_repeat('...', $indent) . $node['uid'], "<br>\n";
if(isset($node['_children']))
foreach($node['_children'] as $child)
print_tree($child, $indent + 1);
}
print_tree($tree[2], 0);
答案 1 :(得分:2)
与任何其他面向对象语言相同 - 创建自己的树和节点类,以满足您的需求。
另一种方法是使用数组创建树(在PHP数组中是关联的,可以嵌套)
我同意Vinicius Kamakura - 如果数据集明显很大,则不应将数据加载到PHP。
答案 2 :(得分:0)
我已根据user187291 answer构建了一个类。
class Tree
{
protected $tree;
protected $rootid;
public function __construct($entries)
{
$this->tree = array();
$this->rootid = PHP_INT_MAX;
/* Build tree under each node */
foreach($entries as $node)
$this->buildTree($this->tree, $node);
}
/* Build tree */
protected function buildTree(&$tree, $node)
{
$i = $node['id'];
$p = $node['pid'];
$this->rootid = min($this->rootid, $p);
$tree[$i] = isset($tree[$i]) ? $node + $tree[$i] : $node;
$tree[$p]['_children'][] = &$tree[$i];
}
/* Print tree */
public function printTree()
{
$this->printSubtree($this->tree[$this->rootid]);
}
/* Print subtree under given node */
protected function printSubtree($node, $depth=0)
{
/* Root node doesn't have id */
if(isset($node['id']))
{
echo str_repeat('...', $depth) . $node['id'], "<br>\n";
}
/* Explore children */
if(isset($node['_children']))
{
foreach($node['_children'] as $child)
$this->printSubtree($child, $depth + 1);
}
}
/* Destroy instance data */
public function __destruct()
{
$this->tree = null;
}
}
用法示例
$entries = array(
array('pid' => 2, 'id' => 3),
array('pid' => 0, 'id' => 2),
array('pid' => 3, 'id' => 7),
array('pid' => 2, 'id' => 4),
array('pid' => 2, 'id' => 6),
array('pid' => 3, 'id' => 8),
array('pid' => 0, 'id' => 9),
);
$tree = new Tree($entries);
$tree->printTree();
希望它有所帮助。当然,您可以向“条目”元素添加字段,只需记住如果要打印它们,请更改“printSubtree”方法。
备注强>: 此类假定节点具有“id”和“pid”的数值,父节点的“id”低于其子节点(在树结构中很常见)。