2012-09-05 21 views
5

que tienen una base de datos con un montón de categorías, algunos son niños:Creación de una función recursiva árbol de categorías

Array 
(
    [0] => Array 
     (
      [id] => 1 
      [name] => Home Improvement 
      [slug] => Home-Improvement 
      [parent] => 
      [user_id] => 1 
      [order] => 1 
     ) 

    [1] => Array 
     (
      [id] => 2 
      [name] => Asbestos Abatement & Removal 
      [slug] => Asbestos-Abatement-Removal 
      [parent] => 1 
      [user_id] => 1 
      [order] => 8 
     ) 

    [2] => Array 
     (
      [id] => 3 
      [name] => Asphalt & Asphalt Products 
      [slug] => Asphalt-Asphalt-Products 
      [parent] => 1 
      [user_id] => 1 
      [order] => 9 
     ) 

    [3] => Array 
     (
      [id] => 4 
      [name] => Bathroom 
      [slug] => Bathroom 
      [parent] => 1 
      [user_id] => 1 
      [order] => 10 
     ) 

    [4] => Array 
     (
      [id] => 5 
      [name] => Kitchen Cabinets 
      [slug] => Kitchen-Cabinets 
      [parent] => 1 
      [user_id] => 1 
      [order] => 11 
     ) 

    [5] => Array 
     (
      [id] => 6 
      [name] => Ceilings 
      [slug] => Ceilings 
      [parent] => 1 
      [user_id] => 1 
      [order] => 12 
     ) 

    [6] => Array 
     (
      [id] => 7 
      [name] => Cleaning 
      [slug] => Cleaning 
      [parent] => 1 
      [user_id] => 1 
      [order] => 13 
     ) 

    [7] => Array 
     (
      [id] => 8 
      [name] => Closet Organizers & Accessories 
      [slug] => Closet-Organizers-Accessories 
      [parent] => 1 
      [user_id] => 1 
      [order] => 14 
     ) 

    [8] => Array 
     (
      [id] => 9 
      [name] => Concrete 
      [slug] => Concrete 
      [parent] => 1 
      [user_id] => 1 
      [order] => 15 
     ) 

    [9] => Array 
     (
      [id] => 10 
      [name] => Contractors & Service Providers 
      [slug] => Contractors-Service-Providers 
      [parent] => 1 
      [user_id] => 1 
      [order] => 16 
     ) 

Lo que estoy tratando de salida es algo como esto:

<ul> 
    <li>Parent 
     <ul> 
      <li>Child</li> 
     </ul> 
    </li> 
    <li>Parent with no Children</li> 
</ul> 

I Estoy tratando de construir un script de árbol recursivo en PHP, pero estoy atascado. Esto es lo que tengo hasta ahora. Estoy atascado en qué hacer entre los demás: y endif; en el foreach (Y estoy usando esa sintaxis solo para facilitar la lectura aquí.) ¿Alguna sugerencia?

echo $this->categories->makeTree(0, $this->db->get('categories')->result_array()); 

public static function makeTree($parent, $array) 
{ 
    if (!is_array($array)) return ''; 

    $output = '<ul>'; 

    foreach($array as $key => $value): 
    if ($value['parent'] == $parent): 
     $output .= '<li>'; 

     if ($value['parent'] == NULL): 
      $output .= $value['name']; 
     else: 

     endif; 
    endif; 

    $output .= '</li>'; 
    endforeach; 

    $output .= '</ul>'; 
    return $output; 
} 

EDIT 1

yo era capaz de conseguir este trabajo, aunque no tengo una llamada base de datos en un bucle foreach, que probablemente no es la mejor idea:

public function makeTree($parent, $array) 
{ 
    if (!is_array($array)) return FALSE; 

    $output = '<ul>'; 

    foreach($array as $key => $value): 
    if ($value['parent'] == $parent): 
     $output .= '<li>'; 

     if ($value['parent'] == NULL): 
      $output .= $value['name']; 

      $subcategories = ci()->db->get_where('categories', array('parent' => $value['id'])); 

      if ($subcategories->num_rows() > 0): 
       $output .= $this->makeTree($value['id'], $subcategories->result_array()); 
      endif; 
     else: 
      $output .= $value['name']; 
      $output .= '</li>'; 
     endif; 
    endif; 

    endforeach; 

    $output .= '</ul>'; 
    return $output; 
} 

EDITAR 2

Aquí está mi solución final, reutilizando la matriz en lugar de hacer un DB qu ery:

public function makeTree($parent, $array) 
{ 
    if (!is_array($array) OR empty($array)) return FALSE; 

    $output = '<ul>'; 

    foreach($array as $key => $value): 
    if ($value['parent'] == $parent): 
     $output .= '<li>'; 

     if ($value['parent'] == NULL): 
      $output .= $value['name']; 

      $matches = array(); 

      foreach($array as $subkey => $subvalue): 
       if ($subvalue['parent'] == $value['id']): 
        $matches[$subkey] = $subvalue; 
       endif; 
      endforeach; 

      $output .= $this->makeTree($value['id'], $matches); 

     else: 
      $output .= $value['name']; 
      $output .= '</li>'; 
     endif; 
    endif; 

    endforeach; 

    $output .= '</ul>'; 

    return $output; 
} 
+0

Actualmente atraviesa 2 niveles. ¿Podemos atravesarlo hasta el nivel n? –

Respuesta

7

aunque esto parece respondió a echar un vistazo here. Con la función que se muestra, puede convertir sus datos planos a datos anidados con solo una iteración. Crear una ul-list a partir de esos datos anidados es muy fácil. Por ejemplo:

function nested2ul($data) { 
    $result = array(); 

    if (sizeof($data) > 0) { 
    $result[] = '<ul>'; 
    foreach ($data as $entry) { 
     $result[] = sprintf(
     '<li>%s %s</li>', 
     $entry['name'], 
     nested2ul($entry['children']) 
    ); 
    } 
    $result[] = '</ul>'; 
    } 

    return implode($result); 
} 

echo nested2ul(array(flat2nested($yourFlatData)); 

Lo bueno de este enfoque es que usted no tiene que reiterar una y otra vez a través de los datos de entrada sólo para encontrar al niño-elementos.

+0

Me gusta eso, pero sigo obteniendo "Offset no definido: 0" en 'return $ m [$ r] [0]; 'en la función makeRecursive.Esa función está esperando datos como 'array (array ('id' => 5273, 'parent' => 0))' mientras que mi matriz es 'Array ([0] => Array ([id] => 1, [parent] ] => 0)) '. ¿Alguna sugerencia sobre cómo puedo solucionar esto? – dallen

+0

@dallen los dos fragmentos que publicó son en realidad iguales. Supongo que el problema es que el valor principal de la raíz es una cadena vacía. Mientras que la función auxiliar usa '0' (ver el parámetro' $ r'). Una cadena vacía como una matriz es un poco problemática, por lo que si pudiera cambiar eso en sus datos de entrada, creo que el resto debería funcionar. – Yoshi

0

intente esto:

$cats = $this->db->get('categories')->result_array(); 

echo $this->categories->makeTree(0, $cats); 

public static function makeTree($parent, $array) 
{ 
    if (!is_array($array)) return ''; 

    $output = '<ul>'; 

    foreach($array as $key => $value): 
    if ($value['parent'] == $parent): 
     $output .= '<li>'; 

     if ($value['parent'] == NULL): 
      $output .= $value['name']; 
     else: 

     endif; 
    endif; 

    $output .= '</li>'; 

    $output .= $this->categories->makeTree($value['parent'], $cats); 

    endforeach; 

    $output .= '</ul>'; 
    return $output; 
} 
+0

No funciona. Acabo de obtener una página corrupta con un error de 500. – dallen

1

Me Solemos ser usar algo como esto, tenga en cuenta

primero esta pieza de código está utilizando obsoleto mysql_ *

segundo se debería tener un campo de base de datos llamado nivel, si NULL es la categoría principal, si tiene un número, es una subcategoría de la categoría con esa n umber como id

function getFamilies($level = 0) { 
    $level++; 
    $sql = "SELECT id from families WHERE level IS NULL"; 
    if (mysql_num_rows($result) > 0) { 
     echo "<ul>"; 
      while($row = mysql_fetch_assoc($result)) { 
       echo "<li>".$row['id']; 
        getSubFamilies($level, $row['id']); 
       echo "</li>"; 
      } 
     echo "</ul>"; 
    } 
} 

function getSubFamilies($level, $id) { 
    $level++; 
    $sqlSubFamilies = "SELECT id FROM families WHERE level = ".$id.""; 
    $resultSubFamilies = mysql_query($sqlSubFamilies); 
    if (mysql_num_rows($resultSubFamilies) > 0) { 
     echo = "<ul>"; 
      while($rowSubFamilies = mysql_fetch_assoc($resultSubFamilies)) { 
       echo "<li>".$rowSubFamilies['id']; 
        getSubFamilies($level, $rowSubFamilies['id']); 
       echo "</li>"; 
      } 
     echo "</ul>"; 
    } 
} 

getFamilies($level = 0); 
+0

en su caso, el nivel es principal, por lo que "seleccionar id, nombre de categorías donde parent es nulo" – Pluda

2

Aquí está mi solución final, reutilizando la matriz en lugar de hacer una consulta DB. Si tiene una mejor solución, ¡publique!

public function makeTree($parent, $array) 
{ 
    if (!is_array($array) OR empty($array)) return FALSE; 

    $output = '<ul>'; 

    foreach($array as $key => $value): 
    if ($value['parent'] == $parent): 
     $output .= '<li>'; 

     if ($value['parent'] == NULL): 
      $output .= $value['name']; 

      $matches = array(); 

      foreach($array as $subkey => $subvalue): 
       if ($subvalue['parent'] == $value['id']): 
        $matches[$subkey] = $subvalue; 
       endif; 
      endforeach; 

      $output .= $this->makeTree($value['id'], $matches); 

     else: 
      $output .= $value['name']; 
      $output .= '</li>'; 
     endif; 
    endif; 

    endforeach; 

    $output .= '</ul>'; 

    return $output; 
} 
0

Creo que este método utilizando la función anónima es muy simple.

//--------------------------- PRINT NESTED CATEGORIES 
$cats_childs = array(); 

$q = $db->query("SELECT id, parent, name FROM categories"); 

while ($r = $db->row($q)) 
{ 
    $cats_childs[$r['parent']][$r['id']] = $r; 
} 

$nested2ul = function($data) use (&$nested2ul, &$cats_childs) { 
    if (!empty($data)) { 
     echo '<ul>'; 
     foreach ($data as $r) { 
      echo '<li>'; 
      echo $r['name']; 
      $flat2ul($cats_childs[$r['id']]); 
      echo '</li>'; 
     } 
     echo '</ul>'; 
    } 
}; 

echo $nested2ul($cats_childs[0]); 
Cuestiones relacionadas