Web lists-archives.com

Re: [PHP] Array to HTML List




On Tue, Mar 29, 2016 at 9:24 PM, Kevin Waterson <kevin.waterson@xxxxxxxxx>
wrote:

> I need to get an array of data (comments) into a threaded HTML list.
>

Quick question: are you sure you want to put the replies into a <ul> inside
an <li> rather than a <ul> *inside* the parent comment's <li>? Putting them
into their own <li> sibling to the parent comment makes them seem to apply
to their parent's parent.

Not too sure how to go about this one.
>
> Maybe I need to build up some sort of tree and traverse it.
>
> http://pastie.org/10778741


Navigating a tree structure (technically a forest) where

   - the root array holds all top-level comments as subtrees,
   - each node is a comment, and
   - each node's children are its comment's direct replies

will be easier than using the raw array. A depth-first traversal will give
you the perfect points at which to take action:

   - Start: Output "<ul>"
   - Visit node: output "<li>$comment</li>"
   - Visit children: output "<li><ul>"; visit each child; output
   "</ul></li>"
   - End: output "</ul>"

Luckily, your path value makes building this tree easy.

    $threads = [];
    foreach ($comments as $comment) {
        $replies = &$threads;
        $ids = explode(',', trim($comment['path'], '{}'));
        $commentId = array_pop($ids);
        if ($ids) {
            foreach ($ids as $id) {
                if (!isset($replies[$id])) {
                    $replies[$id] = ['comment' => null, 'replies' => []];
                }
                $replies = &$replies[$id]['replies'];
            }
        }
        $replies[$commentId] = ['comment' => $comment, 'replies' => []];
    }

And here's how you can output it:

    echo "<ul>\n";
    foreach ($threads as $thread) {
        outputThread($thread);
    }
    echo "</ul>\n";

    function outputThread($thread) {
        echo "<li>{$thread['comment']['content']}</li>\n";
        if ($thread['replies']) {
            echo "<li><ul>\n";
            foreach ($thread['replies'] as $reply) {
                outputThread($reply);
            }
            echo "</ul></li>\n";
        }
    }

Which results in (after running through HTMLTidy):

  <ul>
    <li>Lost my heart and a leg in Australia</li>
    <li>
      <ul>
        <li>I left my heart in sandcrabs bistro</li>
        <li>
          <ul>
            <li>I left my heart in San Francisco</li>
            <li>
              <ul>
                <li>That is the worst joke ever.</li>
                <li>Worst joke evar.</li>
              </ul>
            </li>
            <li>What happened to mudcrab?</li>
          </ul>
        </li>
        <li>I am the tinman, and have no heart</li>
      </ul>
    </li>
    <li>Even on land there are loan sharks</li>
  </ul>

All in one: http://pastie.org/10780881

Cheers!
David