Frage

Ich habe eine Menge Leute lesen verschachtelte Listen zu diskutieren, aber ich frage mich, wie durch einen adjacancy Liste / Baum in PHP iterieren.

Ich habe eine Tabelle mit: id, titel, parent_id

Und ich habe alle Datensätze aus in ein Array ausgewählt namens $ Seiten.

Dann mit dieser PHP:

function makeList($pages, $used) {
    if (count($pages)) {
        echo "<ul>";
        foreach ($pages as $page) {
            echo "<li>".$page['pag_title'];
            $par_id = $page['pag_id'];
            $subsql("SELECT * FROM pages WHERE pag_parent = ".$par_id."");

            // running the new sql through an abstraction layer
            $childpages = $dbch->fetchAll();
            makeList($childpages, $used, $lastused);
            echo "</li>";
        }
        echo "</ul>";
    }
}

Diese Art von Arbeiten, aber ich mit jedem Untermenü am Ende wird wiederholt z.

  • Home
    • News
      • Sub-news
    • Artikel
      • Artikel
  • News
    • Sub-news
  • Artikel
    • Artikel
  • Sub-news
  • Artikel

Ich habe versucht, die aktuelle ID in ein Array hinzufügen, die durch die Funktion übergeben wird, und dann mit in_array zu überprüfen, ob es da ist, aber ich habe keine Freude macht, dass habe.

Jede Hilfe wäre sehr geschätzt werden.

Ich brauche den ganzen Baum so die Wahl Elternteil zu analysieren als 0 ist keine Option

War es hilfreich?

Lösung

Da es schon das SQL der Fall ist, müssen Sie nicht es zu tun haben, außen vor dem ersten Funktionsaufruf.

function makeList($par_id = 0) {
    //your sql code here
    $subsql("SELECT * FROM pages WHERE pag_parent = $par_id");
    $pages = $dbch->fetchAll();

    if (count($pages)) {
        echo '<ul>';
        foreach ($pages as $page) {
            echo '<li>', $page['pag_title'];
            makeList($page['pag_id']);
            echo '</li>';
        }
        echo '</ul>';
    }
}

es Baum speichern, wie Sie auf dieser Seite sehen möchten: Speicher hierarchische Daten in einer Datenbank .

Andere Tipps

Wenn Sie eine Reihe von Seiten gruppiert von Eltern-ID erstellen Sie es ganz einfach zu rekursiv die Liste zu erstellen. Dies wird nur eine Datenbankabfrage erforderlich.

<?php

 //example data
 $items = array(
    array('id'=>1, 'title'=>'Home', 'parent_id'=>0),
    array('id'=>2, 'title'=>'News', 'parent_id'=>1),
    array('id'=>3, 'title'=>'Sub News', 'parent_id'=>2),
    array('id'=>4, 'title'=>'Articles', 'parent_id'=>0),
    array('id'=>5, 'title'=>'Article', 'parent_id'=>4),
    array('id'=>6, 'title'=>'Article2', 'parent_id'=>4)
 );

 //create new list grouped by parent id
 $itemsByParent = array();
 foreach ($items as $item) {
    if (!isset($itemsByParent[$item['parent_id']])) {
        $itemsByParent[$item['parent_id']] = array();
    }

    $itemsByParent[$item['parent_id']][] = $item;
 }

 //print list recursively 
 function printList($items, $parentId = 0) {
    echo '<ul>';
    foreach ($items[$parentId] as $item) {
        echo '<li>';
        echo $item['title'];
        $curId = $item['id'];
        //if there are children
        if (!empty($items[$curId])) {
            makeList($items, $curId);
        }           
        echo '</li>';
    }
    echo '</ul>';
 }

printList($itemsByParent);

Wo kommt $ Seite aus? Sie könnten eine SQL-Injection-Schwachstelle in Ihrem Code haben, wenn Sie zu entkommen sie nicht oder eine vorbereitete Anweisung.

Auch die SELECT-Anweisung in einer for-Schleife springt als schlechte Praxis aus. Wenn die Tabelle nicht so groß ist, wählen Sie dann den Inhalt der gesamten Tabelle und dann durch das Ergebnis in PHP gesetzt laufen, um die Baumdatenstruktur aufzubauen. Dies könnte bis zu n * (n-1) / 2 Iterationen im pathologischen Fall von Ihrem Baum einer verkettete Liste zu sein. Stoppen Sie, wenn alle Knoten wurden dem Baum hinzugefügt, oder die Anzahl der verbleibenden Knoten bleibt gleich von einer Iteration zur nächsten -. Dies bedeutet, dass die übrigen Knoten sind keine Kinder Ihrer Wurzelknoten

Alternativ, wenn Sie Ihre Datenbank rekursive SQL-Abfragen unterstützt, können Sie diese verwenden, und es werden nur die Knoten auswählen, die Kinder des Elternknotens sind. Sie werden immer noch der Baum selbst in PHP Objekt zu bauen. Die Form der Abfrage wäre so etwas wie:

WITH temptable(id, title, parent_id) AS (
  SELECT id, title, parent_id FROM pages WHERE id = ?
  UNION ALL
  SELECT a.id, a.title, a.parent_id FROM pages a, temptable t
   WHERE t.parent_id = a.id
) SELECT * FROM temptable

Ersetzen Sie das '?' in der zweiten Zeile mit der Startseite ID.

Die einfachste Fix wäre einfach sein, wenn Sie die anfängliche Auswahl tun $pages zu setzen (was man nicht zeigen), fügen Sie eine WHERE-Klausel wie:

WHERE pag_parent = 0

(oder NULL ist, je nachdem, wie Sie "Top-Level" Seiten sind zu speichern).

Auf diese Weise werden Sie nicht alle Kinder zunächst auswählen.

Wenn die Tabelle groß wird, Rekursion kann unhandlich bekommen. Ich schrieb eine Blog-Post über eine Rekursion lose Methode: http://www.alandelevie.com/2008/07/12/recursion-less-storage-of-hierarchical-data-in-a-relational-database/

Die Suche nach Top-Eltern, alle Eltern, und alle Kinder eines Knotens (Erweiterungen für Tom Haigh Antwort):

<?php

 //sample data (can be pulled from mysql)
 $items = array(
    array('id'=>1, 'title'=>'Home', 'parent_id'=>0),
    array('id'=>2, 'title'=>'News', 'parent_id'=>1),
    array('id'=>3, 'title'=>'Sub News', 'parent_id'=>2),
    array('id'=>4, 'title'=>'Articles', 'parent_id'=>0),
    array('id'=>5, 'title'=>'Article', 'parent_id'=>4),
    array('id'=>6, 'title'=>'Article2', 'parent_id'=>4)
 );

 //create new list grouped by parent id
 $itemsByParent = array();
 foreach ($items as $item) {
    if (!isset($itemsByParent[$item['parent_id']])) {
        $itemsByParent[$item['parent_id']] = array();
    }

    $itemsByParent[$item['parent_id']][] = $item;
 }

 //print list recursively 
 function printList($items, $parentId = 0) {
    echo '<ul>';
    foreach ($items[$parentId] as $item) {
        echo '<li>';
        echo $item['title'];
        $curId = $item['id'];
        //if there are children
        if (!empty($items[$curId])) {
            printList($items, $curId);
        }           
        echo '</li>';
    }
    echo '</ul>';
 }

printList($itemsByParent);


/***************Extra Functionality 1****************/

function findTopParent($id,$ibp){


    foreach($ibp as $parentID=>$children){ 

            foreach($children as $child){


            if($child['id']==$id){


             if($child['parent_id']!=0){

            //echo $child['parent_id'];
            return findTopParent($child['parent_id'],$ibp);

          }else{ return $child['title'];}

         }              
        }
}
}

$itemID=7;  
$TopParent= findTopParent($itemID,$itemsByParent);





/***************Extra Functionality 2****************/

function getAllParents($id,$ibp){ //full path

foreach($ibp as $parentID=>$nodes){ 

    foreach($nodes as $node){

        if($node['id']==$id){

             if($node['parent_id']!=0){

                $a=getAllParents($node['parent_id'],$ibp);
                array_push($a,$node['parent_id']);
                return $a;

              }else{
                    return array();
                  }

             }
    }
}
}


$FullPath= getAllParents(3,$itemsByParent);
print_r($FullPath);

/*
Array
(
[0] => 1
[1] => 2
)
*/

/***************Extra Functionality 3****************/

 //this function gets all offspring(subnodes); children, grand children, etc...
 function getAllDescendancy($id,$ibp){

 if(array_key_exists($id,$ibp)){

         $kids=array();
         foreach($ibp[$id] as $child){

            array_push($kids,$child['id']);

            if(array_key_exists($child['id'],$ibp))

$kids=array_merge($kids,getAllDescendancy($child['id'],$ibp));

             }

         return $kids;       

     }else{
            return array();//supplied $id has no kids
          }
 }

print_r(getAllDescendancy(1,$itemsByParent));
/*
Array
(
[0] => 2
[1] => 3
)
*/


print_r(getAllDescendancy(4,$itemsByParent));
/*
Array
(
[0] => 5
[1] => 6
)
*/


print_r(getAllDescendancy(0,$itemsByParent));
/*
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
)

*/

?>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top