开发者

PHP recursion issue

开发者 https://www.devze.com 2023-04-09 14:40 出处:网络
My idea is simple: if child->indent, if parent->make bold. Lets say p0 is the parent of p1 and p2, p3 and p4 are the childs of p1. p5 is the independent page like p0. So what i wanna get is

My idea is simple: if child->indent, if parent->make bold.

Lets say p0 is the parent of p1 and p2, p3 and p4 are the childs of p1. p5 is the independent page like p0. So what i wanna get is

p0 (bold font)
[3px]p1(bold font)
[  6px  ]p3
[  6px  ]p4
[3px]p2
p5 (bold font)

The problem is, I can't figure out. how to realize my idea. Tried given functions. No success. It works but indents only first level childs. My recursive php function looks like that

function generateOptions($parent, $level, $padding, $db)
{
    $result=$db->query("SELECT id, name FROM menu WHERE parent='$parent' AND showinmenu!='0'");
    if($level == 0) {$padding=''; $optstyle='bold';}
    else {$optstyle='std'; $padding=' ';}
    while($data=$result->fetch_row()){
        echo generateOption($optstyle.'option', $data, $padding);
        generateOptions($data[0], $level++, $padding, $db);
    }
}

function generateOption($type,$data, $padding){
    switch($type){
    case 'boldoption': return '<option class="bold"  value="'.$data[0].'">'.$padding.$data[1]."</option>\n"; break;
    case 'stdoption': return '<option class="std"  value="'.$data[0].'">'.$padding.$data[1]."</option>\n"; break;
    }
}

And here is the screenshot of my db table. http://prntscr.com/39461

The final working result

function generateOptions($parent, $level, $padding, $db)
{
    $result=$db->query("SELECT id, name FROM menu WHERE parent='$parent' AND showinmenu!='0'");
    $spacer = '&nbsp;&nbsp;'; 
    $padding = str_repeat($spacer, $level);
    while($data=$result->fetch_row()){      
        $children_html = generateOptions($data[0], $level+1, $padding, $db);
        $optstyle = empty($children_html) ? 'std' : 'bold';
        $html .= generateOption($optstyle.'option', $level, $data, $padding); 
        $html .= $children_html;
    }
    return $html;
}

function generateOption($type, $level, $data, $padding){
    $bgcolor=array('0'=>'#开发者_如何学编程f66e02','1'=>'#FF9C4D', '2'=>'#FF9C4D');
    $fontcolor=array('0'=>'#fff','1'=>'#000', '2'=>'#000');
    switch($type){
    case 'boldoption': return '<option class="bold" style="background-color:'.$bgcolor[$level].'; color:'.$fontcolor[$level].'" value="'.$data[0].'">'.$padding.$data[1]."</option>\n"; break;
    case 'stdoption': return '<option class="std"  value="'.$data[0].'">'.$padding.$data[1]."</option>\n"; break;
    }
}


Your indentation problem you can easily solve by multiplying the $level by the number of pixels for a simple indent (3px in your case).

For the bold problem you need a different approach as in your current code, you don't know if the item has any children. The solution to that would be to first get the children in a variable, then add the bold style if any exist, echo the item and only then process the children.

Personally I would first get all data from the database in one pass, then build the hierarchical structure and then use a different function to generate the html. See for example this question for more details.

Edit: Based on your updated question; you can easily optimize it and get rid of the query in the while loop (I'd still go for the option in the previous paragraph by the way...):

  • Don't echo anything, just return a string from your function
  • Get rid of the query in the while function
  • Swap the echo and the function call lines

The result in your function would be something like:

....
$html = '';
while (...)
{
    $children_html = generateOptions($data[0], $level+1, $padding, $db);
    $optstyle = empty($children_html) ? 'std' : 'bold';
    $html .= generateOption($optstyle.'option', $data, $padding); 
    $html .= $children_html;
}
return $html;

and just do a echo generateOptions(...) where you called the function before.


It looks like you might need to be adding more &nbps;'s to your padding where you're just assigning it to one space.

else {$optstyle='std'; $padding='&nbsp;';}

to

else {$optstyle='std'; $padding .='&nbsp;';}


You are trying to map a flat data structure (list) into a tree visually.

Before you can do this in a simple manner, you need to gather the date that is influencing the display to the list.

E.g. you could add a level per entry (1, 2 or 3), which looks like that being your recursive structure already!

Then you pass the modified list to the display routine, that only needs to decide based on the level how to display the entry, for each level:

  1. font-weight: bold;
  2. padding-left: 3px; font-weight: bold;
  3. padding-left: 6px;

The easiest thing to achieve that is to assing a class attribute to the elements parent HTML tag like level-1, level-2 etc..

You already have a $level variable, but I see an error, you increment it all the time, but you only need to pass the value:

generateOptions($data[0], $level+1, $padding, $db);

It might be that this already solves your issue.

0

精彩评论

暂无评论...
验证码 换一张
取 消