1

Im working on creating a modular CMS system in codeigniter and Im having trouble figuring out how to, and whether I can, dynamically add array keys within a function, based on the current depth of the array. For instance, I have data that looks like the following --

[header] => Array ( 
  [blocks] => Array ( 
    [utilitynav] => Array ( 
      [name] => utilitynav [module] => admin [helper] => [model] => [data] => 
    ) 
    [topnav] => Array ( 
      [name] => topnav [module] => admin [helper] => topnav [model] => Db_Sitepages [data] => 
    ) 
    [subhead] => Array ( 
      [name] => subhead [module] => admin [helper] => [model] => [data] => [hasChildren] => 1 
        [blocks] => Array ( 
          [testchild] => Array ( [name] => testchild [module] => admin [helper] => [model] => [data] => [parent] => subhead 
        ) 
      ) 
    ) 
  ) 
)

-- Basically, Blocks have children which are wrapped within the parent block. Im trying to figure out an effective way to manage the levels as right now I am using a separate function to output the children blocks, and if I wanted to be able to go 3 levels deep, I would have to create yet another function. So I am trying to do it recursively, by dynamically adding an array key to my for each statement each time the function reiterates.

For example, this is the function I am using to output the blocks --

  function outputChildBlocks($view_name)
  {

    if(isset($this->view_data[$view_name]['blocks']))
    {
      $html='<div class="blockWrapper">';

        foreach($this->view_data[$view_name]['blocks'] as $block)
        {
            $html.= '<div class="block '.$block['name'].'">';
            $module = $block['module'];
            $name = $block['name'];
            $data['block'] = $block;

            if($block['helper'] != null)
            {
              $this->load->helper($module.'/'.$block['helper']);
            }
            if($block['model'] != null)
            {
              $data['model'] = new $block['model']();
            }

            $html .= $this->load->view($module.'/blocks/'.$name, $data, true);
              if(isset($block['hasChildren']))
              {
                $html .= $this->outputChildChildBlocks($view_name, $name);
              }
            $html.= '</div>';
        }
      $html .= '</div>';
      return $html;
    }
  }

As you can see, at the bottom I am checking if parent has children, and if it does, I call a completely seperate function to output the child blocks (outputChildChildBlocks) -- So, instead, I would like to have the function recognize the depth of the current location, and when it gets to the if statement at bottom, if it does have children, run itself again, add a counter for each level, and then instead of

foreach($this->view_data[$view_name]['blocks'] as $block)

have it go

foreach($this->view_data[$view_name]['blocks'][$name]['blocks'] as $block)

for the 2nd level, then go

foreach($this->view_data[$view_name]['blocks'][$name]['blocks'][$name]['blocks'] as $block)

for the 3rd level, so on and so forth.

Anyways I am not sure how to dynamically add the ['blocks'] key on to the array, for every iteration of the function that has been run for that main block... (obviously I have a [footer] and a [content] block and what not as well with their own sets of blocks)

Anyways sorry if I over explained or complicated the question I have a tendency to do that but I am trying to be as clear as possible and I will be eternally indebted to you if you can show me the best way of making this function recursive!

1
  • so, how did it go? did you manage to solve your recursion issues? :) Commented Jan 8, 2011 at 18:19

1 Answer 1

2

i think you're asking the wrong question. you shouldn't duplicate array keys. you should use the already existing recursive architecture of your array, and match your php code to that :)

i think referring to $this->view_data inside your function messes things up. if you let the function outputChildBlocks take the part of the array holding the blocks that are "up" this time, you should be able to call the same function again from inside itself, but at that time you just pass the correct child of the array you got coming in to the function. make sense?

now, the only problem is calling this function to begin with. calling this function from outside the function requires that you know exactly what to pass to it. shouldn't be a problem though. the caller will probably be a different function inside the same class, and it should then have the possibility of picking the correct element from $this->view_data to pass.

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

6 Comments

Well ya Im not trying to duplicate them exactly I worded that bad, I am trying to add new keys to the reiterated foreach statement each time the function reiterates. Im trying to understand what you are saying but I dont see how it would be beneficial to call the function from outside this function within the same class, when I can just do $this->outputChildBlocks($view_name, $name, $html), and then have it loop through the levels. At least that is what Id like to do ideally (unless there is a better way). - and if it helps to clarify, I am calling the below function once in each of the main
structural blocks, e.g., head, header, content, footer --
damnit didnt mean to hit enter yet. -- <?php echo $layout->outputChildBlocks($view_name); ?> -- and $layout is passed as an object into the views/blocks, but I am not actually outputting the data from the Layout class, so that I can add and remove blocks, scripts, etc as needed, on a per page basis, from the class that is utilizing the layout class.
you wrote foreach($this->view_data[$view_name]['blocks'] as $block) have it go foreach($this->view_data[$view_name]['blocks'][$name]['blocks'] as $block) and i'm saying that this is the wrong approach. if your function could assume that it got an array structure that was already correct for the iteration at hand, then it wouldn't have to be concerned with pointing at the correct depth. the depth would always be the same. well, the depth would always be no depth at all, since the caller of the function controlled the depth.
that means that your layout class would have a method called "outputView($name)" which would call outputChildBlocks, passing it the correct part of the array $this->view_data. and your mains would call <?php echo $layout->outputView($view_name); ?>
|

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.