2012-09-05 16 views
5

Ho un database con un gruppo di categorie, alcuni sono i bambini:Creazione di una funzione ricorsiva albero categoria

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 
     ) 

Quello che sto cercando di output è qualcosa di simile:

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

I Sto cercando di creare uno script ad albero ricorsivo in PHP, ma sono bloccato. Ecco cosa ho finora. Sono bloccato su cosa fare tra il resto: e endif; nel foreach. (E sto usando quella sintassi solo per facilitare la lettura qui.) Qualche suggerimento?

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

ero in grado di ottenere questo lavoro, anche se ho una chiamata di database in un ciclo foreach, che probabilmente non è la migliore 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; 
} 

EDIT 2

Ecco la mia soluzione finale, riutilizzando la matrice invece di eseguire 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

Attualmente sta attraversando 2 livelli. Possiamo attraversarlo fino al livello n? –

risposta

7

se questo sembra rispose uno sguardo here. Con la funzione mostrata puoi convertire i tuoi dati flat in dati annidati con una sola iterazione. La creazione di un ul-list da quei dati annidati è quindi molto semplice. Per esempio:

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)); 

La cosa buona di questo approccio è che non c'è bisogno di ribadire più e più volte nel corso dei dati di input solo per trovare il bambino-elementi.

+0

Mi piace, ma continuo a ricevere "Offset non definito: 0" a "return $ m [$ r] [0]; 'nella funzione makeRecursive.Questa funzione si aspetta dati come 'array (array ('id' => 5273, 'parent' => 0))' considerando che il mio array è 'Array ([0] => Array ([id] => 1, [parent ] => 0)) '. Qualche suggerimento su come posso risolvere questo problema? – dallen

+0

@dallen i due snippet che hai postato sono in realtà gli stessi. Credo che il problema è che il tuo valore genitore di root è una stringa vuota. Mentre la funzione helper usa '0' (vedi il parametro' $ r'). Una stringa vuota come una chiave di array è un po 'problematica, quindi se potessi cambiarla nei tuoi dati di input, penso che il resto dovrebbe funzionare. – Yoshi

0

provare questo:

$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

Non funziona. Ho appena ricevuto una pagina corrotta con un errore di 500. – dallen

1

ho quando arrivavano usare qualcosa di simile, si prega di notare

primo questo pezzo di codice sta usando deprecato mysql_ *

secondo voi dovrebbe avere un campo di database di nome livello, se NULL è la categoria principale, se ha un numero, è una sottocategoria della categoria con quella n umber as 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

nel tuo caso, il livello è padre, quindi "seleziona id, nome da categorie in cui padre è nullo" – Pluda

2

Ecco la mia soluzione finale, riutilizzando la matrice invece di eseguire una query DB. Se hai una soluzione migliore, per favore posta!

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

Penso che questo metodo che utilizza la funzione anonima sia molto semplice.

//--------------------------- 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]); 
Problemi correlati