[PHP] Recursieve Functie

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Shapeshifter
  • Registratie: Januari 2004
  • Laatst online: 07-09 21:38

Shapeshifter

Get it over with

Topicstarter
Ik heb laatst een simpele recursieve functie in PHP geschreven om een balkje te genereren die je absolute locatie op de website aangeeft...

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function BuildNavigator($Navigator, $Parent, $PageName, $PID){
    if($Parent != 'Root'){
        $query = mysql_query("SELECT Parent, PageName, PID FROM Content WHERE PageName = '$Parent'");
        while($row = mysql_fetch_assoc($query)){
            $Parent = $row['Parent'];
            $TPageName = $row['PageName'];
            $TPID = $row['PID'];
        }
        $Navigator = '<a href="index.php?PID='.$TPID.'">'.$TPageName.'</a> >> ' . $Navigator;
        if($Parent != 'Root'){
            $Navigator = BuildNavigator($Navigator, $Parent, $PageName, $PID);
        }
    }
    return $Navigator;
    /* Laatste NavLink kan niet hier, wordt dan n keer geparsed... */
}

$Navigator = BuildNavigator($Navigator, $Parent, $PageName, $PID);
$Navigator = $Navigator . '<a href="index.php?PID='.$PID.'">'.$PageName.'</a>';


De code werkt nu, maar er is iets dat aan me vreet... Zoals je kunt zien kijkt hij of de Parent (de pagina boven de huidige pagina) niet 'Root' is, dan haalt hij de Parentpagina op uit de db en zet deze als de huidige pagina neer, vervolgens wordt deze aan de lijst toegevoegd en checkt hij dezelfde conditie weer. Is de pagina dan nog steeds geen root, dan wordt de functie opnieuw uitgevoerd.

Dit werkt dus allemaal precies zoals ik het in mijn hoofd had. Echter, je zult ook zien dat ik helemaal onderaan nog de huidige pagina aan het lijstje toevoeg:

PHP:
1
$Navigator = $Navigator . '<a href="index.php?PID='.$PID.'">'.$PageName.'</a>';


De reden dat ik dit niet al in de functie doe, is omdat op de plek waar ik het normaal zou zetten (bij de comment) de code n keer doet renderen (waarbij n het aantal keren is dat de functie draait)...

Bijvoorbeeld: wanneer ik een pagina heb met 3 Parents, wordt de functie 3 keer aangeroepen. Als ik die laatste regel op de plek van de comment zou zetten wordt huidige pagina op het einde 3 keer toegevoegd. Je krijgt dan iets van:

Parent1 >> Parent2 >> Parent 3 >> Huidige PaginaHuidige PaginaHuidige Pagina

Ik vind dit erg vreemd gedrag, want ik ging er vanuit dat de functie afgebroken wordt wanneer de functie opnieuw aangeroepen wordt. Heb al vanalles geprobeerd met } else { en } elseif { maar tot nu toe nog geen succes.

Wie weet wat er hier nou precies aan de hand is, waarom gedraagt PHP zich zo?

HP ZBook Studio G3 - Hyundai Ioniq EV Classic - Opel Vivaro-e 75kWh - 22x Prusa i3 MK3S - 8x Prusa MINI+ - Ooznest Workbee 1,5m x 1,5m


Acties:
  • 0 Henk 'm!

Verwijderd

Probeer het eerst eens zonder recursie te doen. In zulke situaties heb je dat namelijk helemaal niet nodig.

En dan nog. Waarom zou een functie worden afgebroken als je hem binnen een functie nogmaals aanroept? Hoe komt je op dat idee?

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:29

crisp

Devver

Pixelated

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Shapeshifter
  • Registratie: Januari 2004
  • Laatst online: 07-09 21:38

Shapeshifter

Get it over with

Topicstarter
Verwijderd schreef op zondag 14 december 2008 @ 13:09:
Probeer het eerst eens zonder recursie te doen. In zulke situaties heb je dat namelijk helemaal niet nodig.

En dan nog. Waarom zou een functie worden afgebroken als je hem binnen een functie nogmaals aanroept? Hoe komt je op dat idee?
Hoe zou je dit zonder recursie willen doen dan? Ik kan zo even geen manier bedenken...

Het kan een x aantal Parents hebben, dus weet je niet van tevoren hoe vaak je iets moet toevoegen.

En het leek me soort van logisch dat een functie afgebroken wordt als je hem opnieuw aanroept, maar blijkbaar niet. Maar dan nog vind ik het apart dat hij aan het einde er n keer de laatste pagina achter zet, in plaats van de laatste pagina steeds achter elke iteratie te zetten.

[ Voor 20% gewijzigd door Shapeshifter op 14-12-2008 13:33 ]

HP ZBook Studio G3 - Hyundai Ioniq EV Classic - Opel Vivaro-e 75kWh - 22x Prusa i3 MK3S - 8x Prusa MINI+ - Ooznest Workbee 1,5m x 1,5m


Acties:
  • 0 Henk 'm!

  • wackmaniac
  • Registratie: Februari 2004
  • Laatst online: 19-09 18:02
Recursie stopt na een nieuwe functie-aanroep alleen als je iets retourneerd in je functie. Het is dus heel logisch dat je string 3 keer wordt afgedrukt.

Als je de functie zou willen laten werken zoals jij wilt zou je BuildNavigator moeten herschrijven in de volgende zin van het woord:
PHP:
1
2
3
4
public function BuildNavigator ( $args ) { 
// ... doe je ding
return $parent->BuildNavigator( $args );
}


Een betere oplossing in dit geval is wellicht wat Cheatah zegt; helemaal geen recursie. In een lusje wil in dit geval ook prima.

Antwoord op je vraag: while( $parent != 'Root' )

[ Voor 4% gewijzigd door wackmaniac op 14-12-2008 13:34 . Reden: vraag beantwoorden ]

Read the code, write the code, be the code!


Acties:
  • 0 Henk 'm!

  • Shapeshifter
  • Registratie: Januari 2004
  • Laatst online: 07-09 21:38

Shapeshifter

Get it over with

Topicstarter
Wat jullie bedoelen is iets in de trant van een while loop?

Daar heb ik eigenlijk nog helemaal niet bij stil gestaan :x

- Lol, langs elkaar heen editten werkt goed!

[ Voor 18% gewijzigd door Shapeshifter op 14-12-2008 13:35 ]

HP ZBook Studio G3 - Hyundai Ioniq EV Classic - Opel Vivaro-e 75kWh - 22x Prusa i3 MK3S - 8x Prusa MINI+ - Ooznest Workbee 1,5m x 1,5m


Acties:
  • 0 Henk 'm!

  • Shapeshifter
  • Registratie: Januari 2004
  • Laatst online: 07-09 21:38

Shapeshifter

Get it over with

Topicstarter
Ik dacht, laat ik nog even het resultaat posten voor andere lezers... Dit is het uiteindelijk geworden:

PHP:
1
2
3
4
5
6
7
8
9
10
11
while($Parent != 'Root'){
    $query = mysql_query("SELECT Parent, PageName, PID FROM Content WHERE PageName = '$Parent'");
    while($row = mysql_fetch_assoc($query)){
        $Parent = $row['Parent'];
        $TPageName = $row['PageName'];
        $TPID = $row['PID'];
    }
    $Navigator = '<a href="index.php?PID='.$TPID.'">'.$TPageName.'</a> >> ' . $Navigator;
}

$Navigator = $Navigator . '<a href="index.php?PID='.$PID.'">'.$PageName.'</a>';


Bedankt voor de hint naar while, was nog helemaal niet in me opgekomen...

HP ZBook Studio G3 - Hyundai Ioniq EV Classic - Opel Vivaro-e 75kWh - 22x Prusa i3 MK3S - 8x Prusa MINI+ - Ooznest Workbee 1,5m x 1,5m


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Kijk eens naar dit uit-ste-ken-de juweeltje van een blogpost van niemand minder dan onze eigen dev-god crisp ;)
Dat scheelt (potentieel) een hele bak queries.

/aandikmodus :P

[ Voor 7% gewijzigd door RobIII op 14-12-2008 20:55 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Shapeshifter
  • Registratie: Januari 2004
  • Laatst online: 07-09 21:38

Shapeshifter

Get it over with

Topicstarter
Hmm, interessante link, ik denk dat ik er even naar ga kijken vanavond.

In mijn achterhoofd had ik al zoiets van... hmmmm ik kan natuurlijk ook gewoon een keer alle info uit de db trekken en daar iets uit opbouwen, maar doordat ik de 'eenvoudige' variant al niet voor elkaar kreeg is dat een beetje weggeebt. Bedankt voor de tip iig...

HP ZBook Studio G3 - Hyundai Ioniq EV Classic - Opel Vivaro-e 75kWh - 22x Prusa i3 MK3S - 8x Prusa MINI+ - Ooznest Workbee 1,5m x 1,5m

Pagina: 1