3

I need to build a table of categories by recursion through an array. It works fine as long as the depth goes deeper but as soon as the depth decreases the HTML output misses the start of a table.

PHP code to build the array:

       if($query->rowCount() > 0) {
        while($result = $query->fetch(PDO::FETCH_OBJ)) {
            $tree[] = $result;
        }
        $childs = array();

        foreach($tree as $item) {
            $childs[$item->parent_id][] = $item;
        }


        foreach($tree as $item) {
            if (isset($childs[$item->id])) {
               $item->childs = $childs[$item->id];
            }
        }

        $tree = $childs[0];
    }
    else {
        // no category blabla
    }

Here is the function to build the table. It fails to work correctly.

    function draw($tree) {
    echo "<table border='1' width='300'>";
    echo "<tr>";
    echo "<td>Name</td><td>Depth</td><td>Parent</td>";
    echo "</tr>";
    foreach($tree as $key => $value) {
        echo "<tr>";
        echo "<td>".$value->name."</td>";
        echo "<td>".$value->depth."</td>";
        echo "<td>".$value->parent_id."</td>";
        echo "</tr>";
        if(isset($value->childs)) {
            draw($value->childs);
        }
    }
    echo "</table>";

}

As requested the HTML Output snippet:

<table border='1' width='300'>
    <tr>
        <td>Name</td>
        <td>Depth</td>
        <td>Parent</td>
    </tr>
    <tr>
        <td>Bad</td>
        <td>5</td>
        <td>5</td>
    </tr>
    <tr>
        <td>Good</td>
        <td>5</td>
        <td>5</td>
    </tr>
</table>
    <!--- BREAK HAPPENS HERE----->
    <tr>
        <td>Both?</td>
        <td>4</td>
        <td>3</td>
    </tr>
    <table border='1' width='300'>
        <tr>
            <td>Name</td>
            <td>Depth</td>
            <td>Parent</td>
        </tr>
        <tr>
            <td>dsadas</td>
            <td>5</td>
            <td>16</td>
        </tr>
    </table>
12
  • Do you mind checking that it works as intended by adding curly braces around your foreach and if statements in the above to clarify exactly what you meant? Having an IF right after a FOREACH could be an accident or deliberate. Please clarify with braces {} ? Commented Feb 28, 2012 at 23:16
  • Why do you have the echo "</table>"; above the draw($value->childs);? get rid of that closing table tag Commented Feb 28, 2012 at 23:18
  • @MyStream the array creation works as intendet. the var_dump of the tree array is exactly as it should be so that isnt the problem. hackartist: i forgot to add that everytime the table jumps into a new depth it should repost the table header with it. that is why the closing table is there. edit: even after removing it the same table breaks happens so that wasnt the problem either Commented Feb 28, 2012 at 23:20
  • @Sepix: It's still hard to read (and not good practice for maintainability (sidepoint)) - and " should be ', but where exactly (what level) do you get unexpected html output? first loop through with no children? Commented Feb 28, 2012 at 23:26
  • html tags come in pairs. in draw you have 1 table open, and at least one but probably more table closes.. that's not going to be balanced. Commented Feb 28, 2012 at 23:27

2 Answers 2

2

do this:

    echo "<tr><td colspan='3'>";
    if(isset($value->childs)) {
        draw($value->childs);
    }
    echo "</td></tr>"

Do this instead:

    if(isset($value->childs)) {
        echo "<tr><td colspan='3'>";
        draw($value->childs);
        echo "</td></tr>"
    }

You are creating a new table within the body of a table. That is invalid HTML. You have to put it in its own TD.

Sign up to request clarification or add additional context in comments.

5 Comments

I am not creating that. the script is which is the problem. I know how the HTML code is supposed to look like the problem is to teach that to the recursive PHP function. :)
@Sepix: Based on what Daan Timmer said, though, try adding same code, but put the tr/td colspan=3 inside the if(isset()) {} block, which should wrap the internal output with a single td - this should next them?
that actually works almost! cant believe it. the only problem now is that the there is no header over the table when he goes into the outer layers. Picture: link
okay. i solved it different in the end but this here definitly gave me the hint i neeeded to understand this recursive stuff. thanks alot ... after 40 hours of struggling i can finally sleep normal again!
@Sepix, no problem. I will alter my answer with what MyStream said. He is correct indeed, my bad!
0
  function draw($tree) {
    if(!$tree) return;
    $nextLevel = array();
    echo "<table border='1' width='300'>";
    echo "<tr>";
    echo "<td>Name</td><td>Depth</td><td>Parent</td>";
    echo "</tr>";
    foreach($tree as $key => $value) {
        echo "<tr>";
        echo "<td>".$value->name."</td>";
        echo "<td>".$value->depth."</td>";
        echo "<td>".$value->parent_id."</td>";
        echo "</tr>";
        if(isset($value->childs) && $value->childs){
           $nextLevel = array_merge($nextLevel, $value->childs);
        }
    }
    echo "</table>";
    draw($nextLeveL);
}

1 Comment

this one works without breaking but prints a table that is not really a tree. it first lists all of layer1 then all of layer 2 then all of layer 2. i have the outcome of yours and how it should look in the end here: link link the 2nd should of course occur without the breaking in the bottom :).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.