Search code examples
phpiteratornested-loops

How to render a definition list from a nested array list with unknown nesting level


i am trying to render a FAQ-list from database data. The database resultset contains a list of arrays (top-level-categories) with each category contain either a set of Q+As following referred to as faqs or another set of categories following referred to as children.

I want to iterate over the resultset, and, when found a 'children'-element, render the following outer markup for the found category.

<div>
   <section>category title</section>

   <!-- In case this category has children, render this block here again 
   to show the sub-categories list under this category -->

   <!-- In case this category has no children, but faqs, render the topics -->
</div>

At http://pastebin.com/czckiNUx i pasted how the data set to be iterated looks like.

I started with a couple nested foreach loops and found the nesting level to be potentially endless (because theoretically one could create nest as much sub-categories under a (sub-)category as wanted) and immediately wondered how to catch this case and render this theoretically unknown level of nesting.

I browsed this platform and read several topics incl. this one and tried to adapt the implementation but stuck with understanding the use of these Iterators. My experience with iterators is almost zero and when i browse the PHP manual i feel somewhat lost since i have no idea where to start or better how to stick these possibilities together to get a working implementation.

While i tried to adapt the solution from the linked topic i found that $iterator ignores all children- and faqs-elements which themselves are arrays and didn't understand why. It outputs only simple type data like strings and numbers. I don't get why and wonder how i have to implement it correctly.

It is required to evaluate every iterated element and check whether its the category title, the category description, the category id or the collection of sub-categories / faqs.

$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($data));

foreach ($iterator as $key => $value)
{
   if ($key == 'children')
   {
      // sub-categories found, find the faqs-elements and render the markup
      // this element might contain further sub-categories (children-elements)
   }
   elseif ($key == 'faqs')
   {
      // collection of Q+As found ... iterate them and render the markup
      // the iteration can't go any deeper
   }
}

How do i have to implement this correctly?


Solution

  • Here's a function that will iterate through your data structure and print out information; you can adapt it as you see fit:

    function iterate(&$array_of_aas)
    {   // we have an array of associative arrays.
        // $x is the associative array
        foreach ($array_of_aas as $x)
        {   echo "Found level " . $x['level'] . " with ID " . $x['id'] . "\n";
    
            if(isset($x['children'])) {
                // found some sub-categories! Iterate over them.
                iterate($x['children']);
            }
            elseif (isset($x['faqs'])) {
                echo "Found some FAQS!\n";
                // collection of Q+As found ... iterate them and render the markup
                // the iteration can't go any deeper
                foreach ($x['faqs'] as $faq) {
                    echo 'ID: ' . $faq['id'] . ", category: " . $faq['catid'] . "\n" . $faq['title'] . "; " . $faq['description'] . "\n";
                }
            }
        }
    }