I've implemented a Modified Preorder Tree Traversal as explained here. My tree is something like this:
+-------+-----------+-----+-----+
| ref | name | lft | rgt |
+-------+-----------+-----+-----+
| NULL | base | 1 | 8 |
| 2 | basic | 2 | 3 |
| NULL | listener | 4 | 7 |
| 1 | test | 5 | 6 |
+-------+-----------+-----+-----+
Everything is ok, but now I tried to implement a PHP search function based on a path, it is, something like this:
$result = searchTree('base.listener.test');
// Now $result is an array with node {1, test}
It means that searchTree returns a subtree based on the path given. If the path doesn't exists it will return an empty array.
My current implementation is a recycled function that loads the tree into a PHP array and then it splits the path and walks through the array. It seems a non-scalable implementation... Any better implementation (perhaps using a mySQL query?).
My current implementation is like this. First I get the whole tree (SELECT * FROM tree) and then I execute this function to make a multidimensional array from this data:
function create_tree($results) {
$return = $results[0];
array_shift($results);
if ($return['lft'] + 1 == $return['rgt'])
$return['leaf'] = true;
else {
foreach ($results as $key =开发者_开发知识库> $result) {
if ($result['lft'] > $return['rgt'])
break;
if ($rgt > $result['lft'])
continue;
$return['children'][] = create_tree(array_values($results));
foreach ($results as $child_key => $child) {
if ($child['rgt'] < $result['rgt'])
unset($results[$child_key]);
}
$rgt = $result['rgt'];
unset($results[$key]);
}
}
unset($return['lft'],$return['rgt']);
return $return;
}
Then I have an array in $tree variable and execute this piece of code:
$t3 = $tree;
$parts = explode('.', $path);
while (isset($parts[0]) && count($parts) > 1 && isset($t3['children']) && $parts[0] == $t3['name']) {
array_shift($parts);
for ($i = 0; $i < count($tree['children']) && $tree['children'][$i]['name'] != $parts[0]; $i++);
$t3 = $tree['children'][$i];
}
return isset($t3) && count($parts) == 1 && $parts[0] == $t3['name']? $t3['children'] : array();
The last line returns the node pointed by the $path (i.e. 'base.listener.test') or an empty array if this path doesn't exists.
If I understand what you're looking for, you want to call:
$result = searchTree('test');
and get search the database for the parents?
SELECT p.name
FROM tree c
INNER JOIN tree p ON p.lft < c.lft AND p.rgt > c.rgt
WHERE c.name = 'test'
ORDER BY p.lft;
精彩评论