Recursieve array opbouwen.
roy - 09/03/2010 21:57
PHP gevorderde
Beste Allemaal,
Ik heb de volgende tabel: menu
ID | Parent_id | title
1 | 0 |
2 | 0 |
3 | 0 |
4 | 2 |
5 | 2 |
6 | 2 |
7 | 5 |
8 | 5 |
9 | 7 |
10| 0 |
Hoe kan ik de database uitlezen en een mooie recursieve array terug geven?
Ik heb in iedergeval een soortgelijke query nodig: select ID, Parent_id From menu where Parent_id = ?
Wie kan mij een stuk verder opweg helpen?
Groeten,
Roy
14 antwoorden
Gesponsorde links
ArieMedia - 09/03/2010 23:43 (laatste wijziging 09/03/2010 23:43)
PHP ver gevorderde
<?php
function BuildMenu($oConn) {
$sql = 'SELECT id, parent, naam, url, extern
FROM menu
ORDER BY volgorde';
$rs = $oConn->Execute($sql);
for($i=0, $x=$rs->RecordCount(); $i<$x; $i++, $rs->MoveNext()) {
$aMenu[$rs->Fields('parent')][$rs->Fields('id')] = array(
'naam' => $rs->Fields('naam'),
'url' => $rs->Fields('url'),
'extern' => $rs->Fields('extern')
);
}
return MaakMenu($aMenu, $aMenu[0]);
}
function MaakMenu($aMenu, $aCurrent) {
$sRet = '<ol>';
foreach($aCurrent as $iID => $aItem) {
if($aItem['extern'] == 'ja') {
$sRet .= '<li class="pijltje"><a href="http://'.$aItem['url'].'">'.$aItem['naam'].'</a></li>';
} else {
$sRet .= '<li class="pijltje"><a href="http://dev.ariemedia.nl/'.$aItem['url'].'">'.$aItem['naam'].'</a></li>';
}
if(isset($aMenu[$iID])) {
$sRet .= MaakMenu($aMenu, $aMenu[$iID]);
}
}
$sRet .= '</ol>';
return $sRet;
}
?>
<?php
function BuildMenu( $oConn ) {
$sql = 'SELECT id, parent, naam, url, extern
FROM menu
ORDER BY volgorde' ;
$rs = $oConn -> Execute ( $sql ) ;
for ( $i = 0 , $x = $rs -> RecordCount ( ) ; $i < $x ; $i ++, $rs -> MoveNext ( ) ) {
$aMenu [ $rs -> Fields ( 'parent' ) ] [ $rs -> Fields ( 'id' ) ] = array ( 'naam' => $rs -> Fields ( 'naam' ) ,
'url' => $rs -> Fields ( 'url' ) ,
'extern' => $rs -> Fields ( 'extern' )
) ;
}
return MaakMenu( $aMenu , $aMenu [ 0 ] ) ;
}
function MaakMenu( $aMenu , $aCurrent ) {
$sRet = '<ol>' ;
foreach ( $aCurrent as $iID => $aItem ) {
if ( $aItem [ 'extern' ] == 'ja' ) {
$sRet .= '<li class="pijltje"><a href="http://' . $aItem [ 'url' ] . '">' . $aItem [ 'naam' ] . '</a></li>' ;
} else {
$sRet .= '<li class="pijltje"><a href="http://dev.ariemedia.nl/' . $aItem [ 'url' ] . '">' . $aItem [ 'naam' ] . '</a></li>' ;
}
if ( isset ( $aMenu [ $iID ] ) ) { $sRet .= MaakMenu( $aMenu , $aMenu [ $iID ] ) ;
}
}
$sRet .= '</ol>' ;
return $sRet ;
}
?>
roy - 10/03/2010 08:37
PHP gevorderde
Ik wil oneindig veel niveaus diep kunnen uitlezen.(recursief)
volgens mij gaat dat niet met bovenstaande. Bovendien wil ik dat de functie een array teruggeeft waarin de niveaus zichtbaar zijn..
Wave6 - 10/03/2010 09:39 (laatste wijziging 10/03/2010 10:16)
PHP beginner
References:)
<?php
$aMenu[0]['id'] = 1;
$aMenu[0]['parent_id'] = 0;
$aMenu[0]['title'] = 'item 1';
$aMenu[1]['id'] = 2;
$aMenu[1]['parent_id'] = 1;
$aMenu[1]['title'] = 'item 2';
$aMenu[2]['id'] = 3;
$aMenu[2]['parent_id'] = 2;
$aMenu[2]['title'] = 'item 3';
$aMenu[3]['id'] = 4;
$aMenu[3]['parent_id'] = 2;
$aMenu[3]['title'] = 'item 4';
function orderMenuArray($p_aArray) {
$aData = $p_aArray;
$iIndex =0;
$aRefs = array();
$aList = array();
while(isset($aData[$iIndex])) {
$rThisref = &$aRefs[$aData[$iIndex]['id']];
$rThisref['id'] = $aData[$iIndex]['id'];
$rThisref['parent_id'] = $aData[$iIndex]['parent_id'];
$rThisref['title'] = $aData[$iIndex]['title'];
if($aData[$iIndex]['parent_id'] == 0) {
$aList[$aData[$iIndex]['id']] = &$rThisref;
} else {
$aRefs[$aData[$iIndex]['parent_id']]['children'][$aData[$iIndex]['id']] = &$rThisref;
}
$iIndex++;
}
return $aList;
}
$aResult = orderMenuArray($aMenu);
print_r($aResult);
?>
<?php
$aMenu [ 0 ] [ 'id' ] = 1 ;
$aMenu [ 0 ] [ 'parent_id' ] = 0 ;
$aMenu [ 0 ] [ 'title' ] = 'item 1' ;
$aMenu [ 1 ] [ 'id' ] = 2 ;
$aMenu [ 1 ] [ 'parent_id' ] = 1 ;
$aMenu [ 1 ] [ 'title' ] = 'item 2' ;
$aMenu [ 2 ] [ 'id' ] = 3 ;
$aMenu [ 2 ] [ 'parent_id' ] = 2 ;
$aMenu [ 2 ] [ 'title' ] = 'item 3' ;
$aMenu [ 3 ] [ 'id' ] = 4 ;
$aMenu [ 3 ] [ 'parent_id' ] = 2 ;
$aMenu [ 3 ] [ 'title' ] = 'item 4' ;
function orderMenuArray( $p_aArray ) {
$aData = $p_aArray ;
$iIndex = 0 ;
while ( isset ( $aData [ $iIndex ] ) ) { $rThisref = & $aRefs [ $aData [ $iIndex ] [ 'id' ] ] ;
$rThisref [ 'id' ] = $aData [ $iIndex ] [ 'id' ] ;
$rThisref [ 'parent_id' ] = $aData [ $iIndex ] [ 'parent_id' ] ;
$rThisref [ 'title' ] = $aData [ $iIndex ] [ 'title' ] ;
if ( $aData [ $iIndex ] [ 'parent_id' ] == 0 ) {
$aList [ $aData [ $iIndex ] [ 'id' ] ] = & $rThisref ;
} else {
$aRefs [ $aData [ $iIndex ] [ 'parent_id' ] ] [ 'children' ] [ $aData [ $iIndex ] [ 'id' ] ] = & $rThisref ;
}
$iIndex ++;
}
return $aList ;
}
$aResult = orderMenuArray( $aMenu ) ;
?>
Zo zou het kunnen werken:)
Deze code is niet het makkelijkste maar als je hem goed leest... dan kom je er wel uit.
Tenminste als je weet wat het nut van een reference is.
Je kunt deze code gewoon kopieren en uitvoeren om te zien wat het resultaat is
roy - 10/03/2010 19:03 (laatste wijziging 10/03/2010 23:17)
PHP gevorderde
Ik wil oneindig veel niveaus diep kunnen uitlezen.(recursief)
De functie moet een array teruggeven, die de niveaus ook weergeeft. (nested array ?)
Array niveau 1 = alle hoofditems
Array niveau 2 = alle subitems
Array niveau 3 = alle sussubitems
etc. etc..
Wie kan me opweg helpen??
avdg - 10/03/2010 23:30 (laatste wijziging 10/03/2010 23:32)
PHP gevorderde
zoiets? (niet getest en nog volledig aan te passen naar wens)
/*Structuur array:
*
* array(
* 'menu' => 'content',
* 'menu2' => array(
* //submenu
* 'menu2 item1' => 'nog wat content dinges'
* )
*);
*/
function menu($array){
//eerst een nieuwe lijst aanmaken
$return = "<ul>\n";
//alle elementen doorlopen
foreach($array as $menu => $content){
if(is_array($content){
$return .= menu($content);
} elseif (is_string($content){
$return .= '<li>' . $content . "<li>\n";
}
}
//natuurlijk de lijst sluiten en dan de output teruggeven
return $return . "</ul>\n";
}
/*Structuur array:
*
* array(
* 'menu' => 'content',
* 'menu2' => array(
* //submenu
* 'menu2 item1' => 'nog wat content dinges'
* )
*);
*/
function menu( $array ) {
//eerst een nieuwe lijst aanmaken
$return = "<ul>\n " ;
//alle elementen doorlopen
foreach ( $array as $menu => $content ) {
$return .= menu( $content ) ;
$return .= '<li>' . $content . "<li>\n " ;
}
}
//natuurlijk de lijst sluiten en dan de output teruggeven
return $return . "</ul>\n " ;
}
roy - 10/03/2010 23:36
PHP gevorderde
Hi,
Dat lijkt al meer op wat ik bedoel.
Maar het probleem zit niet in het uitlezen van de array, dat doe ik met smarty of jQuery..
Het probleem zit hem juist in het maken van die array met de data uit de database.
avdg - 11/03/2010 00:16 (laatste wijziging 11/03/2010 00:39)
PHP gevorderde
Weer wat ongeteste code, hopelijk werkt em
(eigenlijk is het de algoritme dat telt, en niet de code)
/**
* belangrijk: keys moeten in numerieke volgorde staan en parent id moet bestaan(altijd leuk)
* formaat:
* array(
* //v- menu id
* //v- parent id
* 1 => 0,
* 2 => 0,
* 3 => 2
* )
*/
function pointingArray2recursiveArray($array){
$return = array();
foreach($array as $menu => $parent){
//get the path to 0
$position = $parent;
$stack = array();
//get the position of the menu item
while($position){//loop till $position is 0
array_unshift($stack, $position);
}
//attach it recursive
$array = addNode($array, $stack);
}
return $array;
}
/**
* Deze functie helpt met het zetten van een element op zijn juiste plaats
*/
function addNode($array, $stack){
//no need to add nodes on empty stacks
if(null == ($id = shift($stack))){
return $array;
}
//missing value - that should be the last element
if(!isset($array[$id]){
//to avoid looping loops, just add and return, instead of making a new recursion
$array[$id] = array();
} else {
$array[$id] = addNode($array, $id);
}
return $array;
}
/**
* belangrijk: keys moeten in numerieke volgorde staan en parent id moet bestaan(altijd leuk)
* formaat:
* array(
* //v- menu id
* //v- parent id
* 1 => 0,
* 2 => 0,
* 3 => 2
* )
*/
function pointingArray2recursiveArray( $array ) {
foreach ( $array as $menu => $parent ) {
//get the path to 0
$position = $parent ;
//get the position of the menu item
while ( $position ) { //loop till $position is 0
}
//attach it recursive
$array = addNode( $array , $stack ) ;
}
return $array ;
}
/**
* Deze functie helpt met het zetten van een element op zijn juiste plaats
*/
function addNode( $array , $stack ) {
//no need to add nodes on empty stacks
if ( null == ( $id = shift( $stack ) ) ) {
return $array ;
}
//missing value - that should be the last element
//to avoid looping loops, just add and return, instead of making a new recursion
} else {
$array [ $id ] = addNode( $array , $id ) ;
}
return $array ;
}
ArieMedia - 11/03/2010 16:51
PHP ver gevorderde
roy schreef:
Ik wil oneindig veel niveaus diep kunnen uitlezen.(recursief)
volgens mij gaat dat niet met bovenstaande. Bovendien wil ik dat de functie een array teruggeeft waarin de niveaus zichtbaar zijn..
Dat kan zeker wel met de code die ik gaf ;).
Wave6 - 12/03/2010 11:19
PHP beginner
roy schreef:
Ik wil oneindig veel niveaus diep kunnen uitlezen.(recursief)
Als je mijn code eens probeert... gewoon even copy&paste.
Dan zie je wat er gebeurt.
Geloof me, met dit kun je onbeperkt niveau's diep gaan.
roy - 13/03/2010 19:41
PHP gevorderde
Maar het probleem zit niet in het uitlezen van de array, dat doe ik met smarty of jQuery..
Het probleem zit hem juist in het maken van die array met de data uit de database.
Wave6 - 15/03/2010 09:07
PHP beginner
Ja dat doet mijn script toch ook?
Ik laat alleen zien hoe die array in elkaar zit met een print_r?
Ibrahim - 16/03/2010 17:06
PHP expert
Een oneindig aantal niveaus is te bereiken door alle categorieën op te halen met hun id's en hun parentid's. Daarna loop je door deze grote array en sorteer je ze op basis van hun parentid. Zo hoef je maar 1x alle categorieën op te halen, maar kun je alsnog een recursieve functie gebruiken.
Gesponsorde links
Dit onderwerp is gesloten .