[PHP] list tree building (MySQL & PHP)?

Pagina: 1
Acties:
  • 158 views sinds 30-01-2008
  • Reageer

  • cappie
  • Registratie: Februari 2000
  • Laatst online: 17-05-2025

cappie

all lowercase

Topicstarter
ok.. ik heb een table links:

(effe PHP gebruiken voor de tree layout, sorry, moet effe)
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?
/*

id   name                 url                   parent
------------------------------------------------------
1    Games
2    Hardware                              
3    Gamers.nl            gamers.nl             1
4    Twealers.net         tweakers.net/         2
5    Quickzone.cx         quickzone.cx/
6    ITnews  
7    Slashdot.org         slashdot.org/         6
8    The Register         theregister.co.uk/    6
9    cappie's homepage    quickzone.cx/~cappie/
10   Overclocking info                          2
11   Tom's Hardware Guide tomshardware.com/     10

*/
?>

En daar wil ik graag zo'n tree mee bouwen:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?
/*

root
  | 
  |+Games
  |   |
  |   '-Gamers.nl
  |
  |+Hardware
  |   |
  |   |+Overclocking info
  |   |   |
  |   |   '- Tom's Hardware Guide
  |   |
  |   '-Tweakers.net
  |
  |+ITnews
  |   |
  |   |-The Register
  |   '-Slashdot.org
  |
  |-Quickzone.cx
  '-cappie's Homepage

*/ 
?>



Hoe doe ik dit?? :)

Aspire to inspire before we expire | profiel | systeem


  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

recursie + objecten

Verwijderd

Hier heb ik een tijdje geleden ook mee zitten puzzelen en heb het volgende gedaan:
1. The usual query :)
2. Sorteren op parent ID's in een Array (array in array)
3. Weergeven met een recusieve functie.

Mocht je wat code nodig hebben moet je me ff ICQ'en.

  • cappie
  • Registratie: Februari 2000
  • Laatst online: 17-05-2025

cappie

all lowercase

Topicstarter
Op zaterdag 22 september 2001 00:13 schreef wasigh het volgende:
recursie + objecten
voorbeeldje? ik snap wat je met die termen bedoeld, maar ik heb 't nog nooit hoeven gebruiken in PHP :)

Aspire to inspire before we expire | profiel | systeem


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Dit is een vrij lastig probleem helaas. Het valt wel te implementeren, maar echt leuke code wordt het niet volgens mij. Het komt er op neer dat je eerst de root moet zoeken en dan voor elk child van die root zijn childs moet zoeken en voor die childs idem dito... recursie dus :). Met OO kan je die structuur makkelijk bijhouden.

Ik weet uiteraard niet voor welke doeleinden je dit gebruikt, maar je zou ook kunnen overwegen om deze structuur gewoon in XML op te slaan. Je kan deze dan heel gemakkelijk inlezen, of nog beter (en makkelijker): gebruik XSL om het gewenste resultaat te genereren uit de XML file. Zowel de XML file als de XSL file zullen heel simpel zijn. Als je een voorbeeldje wilt zien hoe je dit aan zou kunnen pakken moet je het maar ff zeggen :) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Verwijderd

dunno iets like this:

<?

echo "<HTML><BODY><TABLE CELLPADDING=0 CELLSPACING=0>";

function getlinks($parentid, $level) {
$templevel = $level++;
mysql_connect($host,$username,$password);
mysql_select_db("$database");
$result = mysql_query("SELECT * FROM links WHERE parentid = '$parentid'");
$templevel;
while ($link = mysql_fetch_array($result)) {
for ($x; $< $level; $x++) {
echo "  ";
}
echo "<A HREF=\"$link[url]\">$link[name]</A><BR>\n";
getlinks("$link[parentid]",$templevel);
}

getlinks("","0");

echo "</BODY></HTML";

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Ik genereer zelf zoiets:
code:
1
2
3
4
   / 
      Movies 
        Star Trek 
            Voyager

(met linkjes enzo, maar waar dat is zal ik maar niet zeggen :+ )

En dat doe ik met achter de url zoiets te plakken: browse.php?tree=0|3|60|61

Oftewel, 0 = root, 3 is subtree van root, 60 daarvan, 61 daarvan.

Zoiets zou je kunnen proberen na te maken.
De code voor die 'tree' is dan:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?
function parse_tree($tree)
{
        $search_array = array(
"/^\|/",
"/\|$/",
"/\|\|+/",
);
        $replace_array = array(
"",
"",
"|",
);
        $tree = preg_replace($search_array, $replace_array, $tree);
        $tree_array = explode("|", $tree);
        if($tree_array[count($tree_array)-1] == "")
                unset($tree_array[count($tree_array)-1]);
        $ret_array[curdir] = $tree_array[count($tree_array)-1];
        $ret_array[topdir] = $tree_array[count($tree_array)-2];
        $temp_array=$tree_array;
        array_pop($temp_array);
        $ret_array[toptree] = implode("|", $temp_array);
        $ret_array[treearray]  = $tree_array;
        $ret_array[cleantree] = $tree;

        return $ret_array;
}

function show_tree($tree)
{
        $array = parse_tree($tree);
        return show_treea($array);
}

function show_treea($tree_arr)
{
        global $order;
        include_once("include/misc.php");
        $tree_array = $tree_arr[treearray];

        $html = "<table class='tree' border=1 frame='box' rules='none'>\n";
        $tree="";
        $space = "&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;";
        $num = count($tree_array);
        for($i=0; $i<$num; $i++)
        {
                if($i != 0)
                        $tree.="|";
                $tree.=$tree_array[$i];
                $link="<a href='browse.php?tree=$tree&amp;amp;order=$order' class='tree'>".getfilename($tree_array[$i]) . "</a>";
                $html.="<tr class='tree'><td class='tree'>$space$link</td></tr>\n";
                $space .= "&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;";
        }

        $html .= "</table>\n";
        echo $html;
}

function show_current_dir($dir)
{

}
?>

Misschien heb je d'r wat aan ;)
Maar ik zou dit niet gebruiken om veel dingen onder elkaar te planten.

[edit]
Owja, de entries in de DB hebben overigens alleen maar een 'nummer' en een 'parent' (dus evt 0 indien geen echte parent).

  • cappie
  • Registratie: Februari 2000
  • Laatst online: 17-05-2025

cappie

all lowercase

Topicstarter
dit is wat ik nu heb:

http://quickzone.cx/3.html

Aspire to inspire before we expire | profiel | systeem


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Ok, dan nog ff een mooie oplossing ;) .

Als je deze XML structuur neemt:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0"?>

<root>
    <category name="Games">
        <link name="Gamers.nl" url="http://www.gamers.nl"/>
    </category>

    <category name="Hardware">
        <category name="Overclocking info">
            <link name="Tom's Hardware Guide" url="http://www.tomshardware.com"/>
        </category>

        <link name="Tweakers.net" url="http://www.tweakers.net"/>
    </category>

    <category name="ITnews">
        <link name="The Register" url="http://www.theregister.co.uk"/>
        <link name="Slashdot.org" url="http://www.slashdot.org"/>
    </category>

    <link name="Cappie's Homepage" url="http://www.quickzone.cx/~cappie/"/>
</root>

en je neemt deze heel simpele XSL stylesheet:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="root">
        <html>
            <head>
                <title>Example</title>
            </head>

            <body>
                <h1>My boomarks</h1>

                <ul>
                    <xsl:apply-templates/>
                </ul>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="link">
        <li>
            <a href="{@url}" alt="{@name}">
                <xsl:value-of select="@name"/>
            </a>
        </li>
    </xsl:template>

    <xsl:template match="category">
        <li>
            <xsl:value-of select="@name"/>:
            <ul>
                <xsl:apply-templates/>
            </ul>
        </li>
    </xsl:template>
</xsl:stylesheet>

dan krijg je bij transformatie een leuke HTML file waarin je links in geneste lijsten staan. De code ziet er hier een beetje rommelig uit, maar open het maar ff in een browser om het resultaat te zien.

Dit valt natuurlijk heel makkelijk aan te passen naar wat voor opmaak dan ook (ook non HTML/XML)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0" encoding="UTF-8"?>

<html>
<head>
<title>Example</title>
</head>

<body>
<h1>My boomarks</h1>
<ul>
    <li>Games:
            <ul>
        <li>
<a alt="Gamers.nl" href="http://www.gamers.nl">Gamers.nl</a>
</li>
    </ul>
</li>

    <li>Hardware:
            <ul>
        <li>Overclocking info:
            <ul>
            <li>
<a alt="Tom's Hardware Guide" href="http://www.tomshardware.com">Tom's Hardware Guide</a>
</li>
        </ul>
</li>

        <li>
<a alt="Tweakers.net" href="http://www.tweakers.net">Tweakers.net</a>
</li>
    </ul>
</li>

    <li>ITnews:
            <ul>
        <li>
<a alt="The Register" href="http://www.theregister.co.uk">The Register</a>
</li>
        <li>
<a alt="Slashdot.org" href="http://www.slashdot.org">Slashdot.org</a>
</li>
    </ul>
</li>

    <li>
<a alt="Cappie's Homepage" href="http://www.quickzone.cx/~cappie/">Cappie's Homepage</a>
</li>
</ul>
</body>
</html>

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Je kan trouwens eventueel nog heel gemakkelijke via een parameter aangeven in welke knoop er begonnen moet worden :)

Zie daarvoor:
[topic=232403/1/25]

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • cappie
  • Registratie: Februari 2000
  • Laatst online: 17-05-2025

cappie

all lowercase

Topicstarter
wat ik nu nog moet doen is d'r dus een tree van bouwen IPV van een doorclick directory dingetje.. want da's lame :)

enig idee hoe ik dit 't beste kan doen?

source: http://quickzone.cx/3.phps

Aspire to inspire before we expire | profiel | systeem


  • cappie
  • Registratie: Februari 2000
  • Laatst online: 17-05-2025

cappie

all lowercase

Topicstarter
thnx mbravenboer,

als het zo simpel in XML kan, dan zou 't toch ook te doen moeten zijn in PHP in samenwerking met MySQL ?

ik ga effe op wat code depositories kijken..

de rest: ook bedankt :)

Aspire to inspire before we expire | profiel | systeem


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Het punt is dat boom-structuren niet erg makkelijk te verwezelijken zijn in een relationele database. Queries hebben altijd een simpele lijst van records als resultaat en dat moet je dus maar zelf naar een boom om gaan zetten. Dit kan je dan makkelijk doen met een recursieve functie.

XML staat een veel rijkere mogelijkheid (uiteraard alleen syntax suiker) van data-structurering toe en je kan er dus ook heel gemakkelijk een boom in opschrijven. In feite is elk XML document al een boom.

De toepassing van XSL gaat zo makkelijk omdat XSL structurele recursie toepast. In elke knoop die wordt bezocht wordt er simpelweg gekeken welke template er toegepast moet worden. Met behulp van apply-templates roep je de recursieve stap aan.

Door de aard van XML en XSL is dit probleem dus zo makkelijk op deze manier op te lossen.... Door de aard van relationele databases is dit een stuk lastiger met MySQL. Je kan in PHP gewoon XSL stylesheets toepassen, dus wat houd je tegen om het makkelijk te doen?

Databases zijn niet voor alles de beste oplossing. XML en XSL ook niet :) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Kleine tip over toepassing in PHP/MySQL in 'pseudo' code:
code:
1
2
3
4
5
6
7
8
9
10
11
createTree(List items, int currentNode)
{
   List children = filter items where parentID == currentNode.id
   
   foreach(item in children)
   {
      verwerk item in output

      createTree(items, item.id)
   }
}

Inititiele aanroep met alle items en currentNode = 0.

Valt wel mee toch? Het kan zeker veel efficienter, maar dit is een aardig begin.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • pimlie
  • Registratie: November 2000
  • Laatst online: 19-09 19:50
Ik weet niet of je erveel aan hebt, de code is namelijk erg langzaam maar ik gebruik het volgende script ervoor:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?
// functions to generate item list
    function TranslateCode ($code) {
         $IMGS[1] = "[img]\"fake.gif\"[/img]";
         $IMGS[2] = "[img]\"fake.gif\"[/img]";
         $IMGS[3] = "[img]\"fake.gif\"[/img]";
         $IMGS[4] = "[img]\"fake.gif\"[/img]";
         $IMGS[5] = "[img]\"fake.gif\"[/img]";
         $code = round($code);
         $string = ereg_replace("([1-5]{1})", "\$IMGS[\\1]", $code);
         eval("\$code = \"$string\";");
         return $code;
    }

    function PrintChildren($parent, $imgs_code = 0, $b = -1) {
         global $db,$group, $var;
         $CODE_LINE = 1;
         $CODE_EMPTY = 2;
         $CODE_ROOT_SPLIT = 3;
         $CODE_ROOT_END = 4;

         /* Maak SQL statement */
            $sql = "SELECT id, hoofdstuk, naam FROM menu WHERE refid='$parent' ORDER BY refid ASC";
         $result = mysql_query($sql) or die(mysql_error());

         $childcount = mysql_num_rows($result); // childcount = het aantal kinderen
         if ($childcount) {
              $count = 1;
              $imgs_code_kopie = $imgs_code;
              while ($row = mysql_fetch_object($result)) {
                      /* Schrijf de kindjes */
                      $imgs_code = $imgs_code_kopie;
                      if ($childcount == $count) {// dit is het laatste item, dus rootend
                          $imgs_code .= $CODE_ROOT_END;
                      }else{
                          $imgs_code .= $CODE_ROOT_SPLIT;
                      }
                      $plaatjes = TranslateCode($imgs_code);
                echo "<tr>\n";
                echo "\t<td>$plaatjes ".$row->hoofdstuk." ".stripslashes($row->naam)."</td>\n";
                echo "<td><a href='index2.php?p=".$row->id."'>".$row->id."</a></td>";
                echo "</tr>\n";
                 /* Roep deze functie nogmaals aan */
                  $imgs_code = $imgs_code_kopie;
                  if ($childcount == $count) {// dit is het laatste item, dus een leeg plaatje
                          $imgs_code .= $CODE_EMPTY;
                  }else{ // anders een lijntje
                          $imgs_code .= $CODE_LINE;
                  }
                  PrintChildren($row->id, $imgs_code, &amp;amp;amp;$b);
                  $count++;
                 }
        }
    }
// end

if(!$p) $p=0;

echo "<table>";
echo PrintChildren($p);
echo "</table>";
?>

Hier kan je een voorbeeldje zien.

Verwijderd

Bovenstaande code van pimlie kun je krijgen van phpfreakz.com, en dan het artikel van hoe een forum te maken.De uitleg kan je wel helpen met je probleem.

URL =
Artikel over forum

  • Yohost!
  • Registratie: Juni 2000
  • Laatst online: 21-09 19:54
Ik heb zoiets dus ook gemaakt.

Je moet dus eerst een lijst met roots maken.
Dan krijg je dus een lijst met childs die als parents het ID van de roots hebben.

Die Childs kunnen dan dus ook weer root zijn van childs onder hun.

  • Rense Klinkenberg
  • Registratie: November 2000
  • Laatst online: 15-09 23:45
Wat je ook kan doen is gebruik maken van XML / XSLT. Alleen niet de data zelf al als XML opslaan, maar tijdens de aanvraag laten genereren m.b.v. DOMXML.

Je kan dat in een paar stappen doen:
  • Opvragen van alle rijen uit de database
  • Afhankelijk van de parentid de tekst aan de goede node hangen<li> Met de XSLT-functies van PHP kan je daarna een XSLT toepassen.
</li>

  • cappie
  • Registratie: Februari 2000
  • Laatst online: 17-05-2025

cappie

all lowercase

Topicstarter
Mischien moet ik maar gewoon geen tree willen bouwen, en 't gewoon simpel houden ofzo :)

't schijnt gewoon niet fatsoenlijk te kunnen met PHP en MySQL.

thnx anyway :)

Aspire to inspire before we expire | profiel | systeem


  • killercow
  • Registratie: Maart 2000
  • Laatst online: 20-09 10:57

killercow

eth0

wedden dat je een mooie tree kan bouwen? heb hier zelfs code liggen die je dir structuur uistschrijft, als dat geen tree is weet ik het ook niet meer, nu alleen nog ff iemand die me helpt met het uitpluizen van een stukkie jscript, zodat het een echte explorer look a like wordt.

iemand? naja hier is de code.

uhm ff kijken :)
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?
//config
$mode="list"; // mode of writing accepts (list, XML, explorer, asci)
$root_dir=$DOCUMENT_ROOT;
$http_root="http://www.pc-gamers.com";
$date=1;
$size=1;
$link=1;
$subdir="themes";
//end config

echo"Subdirs and files for ".$http_root."/".$subdir;
if($subdir!="" and $subdir!=NULL){
$startdir=$root_dir."/".$subdir;
} else {
$startdir=$root_dir;
}
viewdir($startdir,'');

function give_create_date($date) {
    $return = date("d. ",$date);
    $month = date("M",$date);
    switch ($month) {
        case "Jan":
            break;
        case "Feb":
            break;
        case "Mar":
            $month = "Mar";
            break;
        case "Apr":
            break;
        case "May":
            $month = "Mij";
            break;
        case "Jun":
            break;
        case "Jul":
            break;
        case "Aug":
            break;
        case "Sep":
            break;
        case "Oct":
            $month = "Okt";
            break;
        case "Nov":
            break;
        case "Dec":
            $month = "Dec";
            break;
    }
    $return .= $month;
    $return .= date(" Y H:m",$date);
    return $return;
}

function viewdir($dir,$olddir){
    global $root_dir, $mode, $date, $size, $http_root, $link,$startdir;
    if($mode=="list"){
        $parent="<ul>";
        $parentend="</ul>";
        $child="<li>";
        $childend="</li>";
    } 
    echo"$parent";
    chdir($dir);
        $d=dir($dir);
        while($file=$d->read()) {
            if($file!=".") {
                    if($file=="..") {
                        if($file!=$root_dir) {
                            clearstatcache(); 
                        } 
                    } else {
                        if(is_dir($file)) {
                            echo"$child<b>$file</b>$childend";
                            viewdir($dir."/".$file,$dir);
                        } else {
                                echo"$child";
                                clearstatcache(); 
                                if($link==1){
                                    $linkdir=$http_root.substr($dir,strlen($root_dir));
                                     echo"<a href=".$linkdir."/".$file.">".$file."</a> - ";
                                } else {
                                    echo"$file - ";
                                }
                                if($size==1){
                                    $size_of=filesize($file);
                                    if ($size_of!="" or $size_of!=NULL or $sizeoff!=0){
                                    echo"$size_of bytes - ";}
                                }
                                if($date==1){
                                    $date_of=give_create_date(filemtime($file));
                                    echo "$date_of";
                                }
                                echo"$childend";
                        }    
                    }
            }

        }
if(strstr($olddir,$startdir)!=false){
    chdir($olddir);
}

    echo"$parentend";
}
?>

eennnuuhh je kunt hem bekijken op: http://www.pc-gamers.com/VIEWDIR.PHP

openkat.nl al gezien?


  • Yohost!
  • Registratie: Juni 2000
  • Laatst online: 21-09 19:54
Inderdaad, het enige wat er dus nog bij moet is een stuk javascript zodat je als je op een + klikt er een hele lijst uitvouwt.

  • xshredx
  • Registratie: Maart 2001
  • Laatst online: 19-09 22:50

xshredx

 

op www.devshed.com kan je hierover ook een redelijke tutorial vinden die je wat verder zou moeten kunnen helpen om wat startcode te hebben...

bv. http://www.devshed.com/Server_Side/PHP/ExtensibleMenuClass/

en over tree building is er eigenlijk in het algemeen wel redelijk veel te vinden

  • Yohost!
  • Registratie: Juni 2000
  • Laatst online: 21-09 19:54
Inderdaad, als je goed zoekt zijn er ook nog wel kant en klare php tree scripts te downloaden.
Pagina: 1