He estado buscando en la Lista de adyacencia y en el Conjunto anidado para encontrar la solución de árbol óptima.Lista de adyacencia frente al modelo de conjunto anidado
Hasta ahora, pensaba que una de las principales ventajas de Nested Set Model era que podía usar una consulta SQL y un código para obtener un árbol completo. Pero es complicado actualizar/insertar nodos y todo el árbol puede dañarse fácilmente.
Entonces tropecé con estos dos mensajes:
Recursive categories with a single query?
http://www.sitepoint.com/forums/showthread.php?t=570360
El siguiente código me permite usar lista de adyacencia con una consulta SQL. Me parece que la Lista de adyacencia es más fácil de actualizar y es menos probable que corrompa todo el árbol.
¿Qué opinas sobre este código?
Generar una matriz multidimensional para reflejar la estructura de árbol
$nodeList = array();
$tree = array();
$query = mysql_query("SELECT id, title, page_parent FROM categories ORDER BY page_parent");
while($row = mysql_fetch_assoc($query)){
$nodeList[$row['id']] = array_merge($row, array('children' => array()));
}
mysql_free_result($query);
foreach($query AS $row){
$nodeList[$row['id']] = array_merge($row, array('children' => array()));
}
foreach ($nodeList as $nodeId => &$node) {
if (!$node['page_parent'] || !array_key_exists($node['page_parent'], $nodeList)) {
$tree[] = &$node;
} else {
$nodeList[$node['page_parent']]['children'][] = &$node;
}
}
unset($node);
unset($nodeList);
Preparar una lista desordenada con nodos anidados
function printMenu ($arrTreeToTraverse, $ext = '.html', $breadcrumb = '') {
// Pre loop stuff
echo "<ul class=\"sf-menu\">\r\n";
foreach ($arrTreeToTraverse as $objItem) {
// Stuff relevant to the item, before looping over its children
if ($objItem['page_parent'] != 0) {
$breadcrumb .= '/'.$objItem['uri'];
}
else
{
$breadcrumb .= $objItem['uri'];
}
if ($objItem['uri'] == 'index') {
echo '<li><a href="/">'.$objItem['title'].'</a>';
} else {
echo '<li><a href="'$_SERVER['SERVER_NAME'].'/'.$breadcrumb.$ext.'">'.$objItem['title'].'</a>';
}
if ($objItem['children']) {
echo "\r\n";
// Call the function again on the children
printMenu($objItem['children'], $ext, $breadcrumb);
}// if
// Extend breadcrumb if it is a child or
// reset breadcrumb if first level of tree
$parent = explode('/', $breadcrumb);
if ($objItem['page_parent'] != 0) {
$breadcrumb = $parent[0];
} else {
$breadcrumb = '';
}
echo "</li>\r\n";
}// foreach
// Post loop stuff
echo "</ul>\r\n";
}// function
printMenu($navigation, '.html');
Se ve bien aparte del 'foreach ($ query AS $ row)' que no es necesario y generará un error. – Fanis