3

My brain doesn't seem to want to work this morning.. i have the following array:

private $nav_pages = [['0', 'Home', 'home'],
                      ['0', 'About Us', 'about'],
                      ['0', 'Our Services', 'services'],
                      ['1', 'PROCURE TO PAY (P2P)', 'procure'],
                      ['1', 'ORDER TO CASH (02C)', 'cash'],
                      ['1', 'GENERAL ACCOUNTING', 'general'],
                      ['2', 'Charting of Accounts', 'charting'],
                      ['2', 'General Ledger Maintenance', 'maintenance'],
                      ['2', 'Accounts Receivable Services', 'receivable'],
                      ['2', 'Accounts Payable Services', 'payable'],
                      ['2', 'Reconciliation of Bank Accounts and Credit Cards', 'reconciliation'],
                      ['2', 'Preparing Financial Statements', 'statements'],
                      ['2', 'Payroll Processing', 'payroll'],
                      ['1', 'CLOSING & REPORTING', 'closing'],
                      ['0', 'How It Works', 'how-it-works'],
                      ['0', 'Contact Us','contact'],
                      ['0', 'Careers', 'careers']];

This is then fed to a php page which is meant to lay out a multi-layered pure css drop down menu.. the php page code is:

<ul class="<?php echo $ul_class; ?>">

<?php $this_layer = 0;

// place array content into variables
foreach ($links as $link) {

    $item_layer  = $link[0];
    $item_string = $link[1];
    $item_link   = $link[2];

    if ($item_layer > $this_layer) { ?>
        <ul>
    <?php $this_layer++; }
    elseif ($item_layer == $this_layer) { ?>
        <li class="<?php echo $item_link; ?>">
            <a class="<?php echo $item_link; ?>"
               href="/<?php echo $item_link; ?>">
                <?php echo $item_string; ?>
            </a>
        </li>
    <?php }
    elseif ($item_layer < $this_layer) { ?>
        </li></ul>
    <?php $this_layer--; } ?>
<?php } ?>

The output is not correct however as the above code always closes the list item containing the second layer before the second layer is ready to be closed. if that makes sense..

<ul class="pages_nav">
<li class="home">
    <a class="home"
       href="/home">
        Home                
    </a>
</li>
<li class="about">
    <a class="about"
       href="/about">
        About Us                
    </a>
</li>
<li class="services">
    <a class="services"
       href="/services">
        Our Services                
    </a>
</li>
<ul>
    <li class="cash">
        <a class="cash"
           href="/cash">
            ORDER TO CASH (02C)                
        </a>
    </li>
    <li class="general">
        <a class="general"
           href="/general">
            GENERAL ACCOUNTING                
        </a>
    </li>
    <ul>
        <li class="maintenance">
            <a class="maintenance"
               href="/maintenance">
                General Ledger Maintenance                
            </a>
        </li>
        <li class="receivable">
            <a class="receivable"
               href="/receivable">
                Accounts Receivable Services                
            </a>
        </li>
        <li class="payable">
            <a class="payable"
               href="/payable">
                Accounts Payable Services                
            </a>
        </li>
        <li class="reconciliation">
            <a class="reconciliation"
               href="/reconciliation">
                Reconciliation of Bank Accounts and Credit Cards                
            </a>
        </li>
        <li class="statements">
            <a class="statements"
               href="/statements">
                Preparing Financial Statements               
            </a>
        </li>
        <li class="payroll">
            <a class="payroll"
               href="/payroll">
                Payroll Processing                
            </a>
        </li>
        </li></ul>
    </li></ul>
<li class="contact">
    <a class="contact"
       href="/contact">
        Contact Us                
    </a>
</li>
<li class="careers">
    <a class="careers"
       href="/careers">
        Careers                
    </a>
</li>

SOLUTION:

<ul class="<?php echo $ul_class; ?>">

<?php $this_layer = 0;

// place array content into variables
foreach ($links as $link) {

    $item_layer  = $link[0];
    $item_string = $link[1];
    $item_link   = $link[2];

    // check if link needs to be manipulated
    switch($do) {
        case 'strtolower':
            $item_string = strtolower($item_string);
            break;
        case 'strtoupper':
            $item_string = strtoupper($item_string);
            break;
    } ?>

    <?php if ($item_layer > $this_layer) { ?>
        <ul>
        <li class="<?php echo $item_link; ?>">
            <a class="<?php echo $item_link; ?>"
               href="/<?php echo $item_link; ?>">
                <?php echo $item_string; ?>
            </a>
    <?php $this_layer++; }
    elseif ($item_layer == $this_layer) { ?>
        </li><li class="<?php echo $item_link; ?>">
            <a class="<?php echo $item_link; ?>"
               href="/<?php echo $item_link; ?>">
                <?php echo $item_string; ?>
            </a>
    <?php }
    elseif ($item_layer < $this_layer) { ?>
        </li></ul></li><li class="<?php echo $item_link; ?>">
        <a class="<?php echo $item_link; ?>"
           href="/<?php echo $item_link; ?>">
            <?php echo $item_string; ?>
        </a>
        <?php $this_layer--; } ?>
<?php } ?>

4
  • shouldn't you have like: <ul><li>Main item<ul><li>subitem</li></ul></ul> Commented Feb 20, 2013 at 11:17
  • exactly! but i can't get the logic of the forelse loop to do JUST that.. like i said.. my head isn't working this morning.. Commented Feb 20, 2013 at 11:19
  • Let me answer that for you sec Commented Feb 20, 2013 at 11:20
  • How can i be displaying the first item anyway? if the level is higher you don't echo the li, still your html shows the items. Am i that blind? Commented Feb 20, 2013 at 11:33

2 Answers 2

1

Never close the the li tag, close it when you add something

foreach ($links as $link) {
    if ($item_layer > $this_layer) { 
        echo '<ul><li> ......';
        this_layer++; 
    }elseif ($item_layer == $this_layer) {
        echo '</li><li>......';
    }elseif ($item_layer < $this_layer) {
        echo '</li></ul><li>......';
        $this_layer--; 
    }
}

Last you probably need to add a echo '</li></ul>' outside of the foreach to close everything

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

Comments

1

Had to rework the code a little, usually i organize the php menu structure in tree form makes it easier to parse into html menus, but here it is:

<ul class="<?php echo $ul_class; ?>">
<?php 
$this_layer = 0;
$closeit = false;
// place array content into variables
foreach ($nav_pages as $link) {
    $item_layer  = $link[0];
    $item_string = $link[1];
    $item_link   = $link[2];

    if ($item_layer > $this_layer) { 
      // Changing level, dont close the previous li
      ?><ul><?php 
      $closeit = false;
      $this_layer++; 
    }
    if ($item_layer == $this_layer) { 
      // Same level, check if you need to close previous li
      if ($closeit) {
        ?></li><?php
      }
      // Render the li
    ?>
  <li class="<?php echo $item_link; ?>">
    <a class="<?php echo $item_link; ?>"
        href="/<?php echo $item_link; ?>">
      <?php echo $item_string; ?>
    </a>
    <?php 
      // Close it on next loop
      $closeit = true;
    }
    elseif ($item_layer < $this_layer) { 
      // Changing layer back down, close the previous li and the current level ul
      ?>
  </li>
</ul>
    <?php
      $this_layer--; 
    } 
} 
// Finished loop, there should still be a li waiting to be closed
if ($closeit) { 
  ?></li><?php 
}
// Close menu
?>
</ul>

Should be working, let me know if it isnt

Suggested php menu structure:

$menu = array(
    array(
        "url"=>"/place.php",
        "text"=>"Go to place"
    ),
    array(
        "url"=>"/place2.php", // not necessary
        "text"=>"with submenu",
        "children"=>array(
            array(
                "url"=>"/placewithinplace2.php",
                "text"=>"submenu item"
            )
        )
    )
);

7 Comments

nope.. that doesn't solve the problem of the list item closing before the associated sub menu is in place.
Edited the post, the previous answer did not solve the problem.
Nope. Sorry.. The ul's don't close.. but let me have a look through your code. I see what you are getting at by adding a variable to close determine whether to close or not (originally hoping to avoid that).
Strange, i tested it with your menu array and it rendered valid html. Are you sure the uls dont close? You should have a </li></ul></li></ul> after the Payroll Processing link. These menus are a lot easier to build in a recursive manner but for that its easier if the menu array is built as a tree. (my results: pastebin.com/xipQSbJh)
Edited answer with suggested menu structure, has the advantage of being easier to read, allowing new attributes to be added to menu items without affecting the existing code, and makes creating a recursive function to render it extremely easy.
|

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.