2

I have some PHP code I've been working on for a good few days now. I'm trying to generate a formatted list of rules from a flat array. I got help here before on how to turn the flat array into a tree array, but I'm having difficulty writing a recursive function that can go through it and successfully break it down at points at such depths where I'd like the rules to be members of an unordered list from the markup that gets printed.

<?php 
$data = array(
    '0'        => 'Introduction',
    '4'        => 'General',
    '4.1'      => 'Chat',
    '4.1.1'    => 'Do',
    '4.1.1.9'  => 'This',
    '4.1.1.10' => 'That',
    '4.1.1.11' => 'Other',
);

$struct = array(
    'children' => array()
);

foreach ($data as $ruleID => $content)
{
    $parent =& $struct;
    foreach (explode('.', $ruleID) as $val)
    {
        if (!isset($parent['children'][$val]))
        {
        $parent['children'][$val] = array(
                'content' => '',
                'children' => array()
            );
        }
        $parent =& $parent['children'][$val];
    }
    $parent['content'] = $content;
}


$out = '';
$rules = array_pop($struct);
format_rule($rules);
var_dump($rules);
echo $out;

function format_rule($arr, $depth=0)
{
    global $out;
    echo "depth: $depth\n";
    foreach($arr as $key => $val)
    {
        switch($depth)
        {
            case 0:
                $out .= '<h1>'.$val['content']."</h1><br />\n";
                break;
            case 1:
                $out .= '<h2>'.$val['content']."</h2><br />\n";
                break;
            case 2:
                $out .= '<h3>'.$val['content']."</h3><br />\n";
                break;
            default:
                $out .= '<li>'.$val['content']."</li>\n";
                break;
        }
        if(isset($val['children']) && count($val['children']) > 0)
        {
            if($depth > 2)
            {
                $out .= '<ul>';
                format_rule($val['children'], ++$depth);
                $out .= '</ul>';
            }
            else
            {
                format_rule($val['children'], ++$depth);
            }
        }
    }
}

The output at the moment is:

<h1>Introduction</h1><br />
<h1>General</h1><br />
<h2>Chat</h2><br />
<h3>Do</h3><br />
<li>This</li><br />
<li>That</li><br />
<li>Other</li><br />

Which is great, except from my code I'm pretty sure the section under 'Do' should have a <ul> around it.

2 Answers 2

2

change your code to :

if($depth >= 2)

note: remember the count starts at 0, not 1.

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

1 Comment

I feel robbed that I caved and came here when I was so close.
2

Try this:

<?php 
$data = array(
    '0'        => 'Introduction',
    '4'        => 'General',
    '4.1'      => 'Chat',
    '4.1.1'    => 'Do',
    '4.1.1.9'  => 'This',
    '4.1.1.10' => 'That',
    '4.1.1.11' => 'Other',
);

function get_level($key){
    return count(explode(".",$key));
}

function set_tag(&$array,$key,$item,&$ul_started){
    $level = get_level($key);
    switch($level){
        case 1:
        case 2:
        case 3:
            if($ul_started){
                $array[$key] = "</ul><h".$level.">".$item."</h".$level."><br>";
                $ul_started=false;
            }else{
                $array[$key] = "<h".$level.">".$item."</h".$level."><br>";
            }
        break;
        default:
            if(!$ul_started){
                $array[$key] = "<ul><li><strong>".$item."</strong></li><br>";
                $ul_started=true;
            }else{
                $array[$key] = "<li><strong>".$item."</strong></li><br>";
            }
        break;
    }
}

$ul_started = false;

foreach($data as $key=>$item){
    set_tag($data,$key,$item,$ul_started);
}

if($ul_started){
    $keys = array_keys($data);
    $data[$keys[count($data)-1]] .= "</ul>";
}

echo implode("",$data);
?>

2 Comments

+1 for effort, but just changing depth > to >= and then giving default <li> tags makes my code work just how I wanted. Subsequent depths get embedded in more <ul> which is perfect.
yea, I just wanted to challenge myself.

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.