Jump to content

Dynamic Multi-Level Drop Down Menu


maxudaskin

Recommended Posts

Hi guys, I'm still not having any luck with coming up with an idea of how to make my multi-level drop down menu work with items from a database. I don't necessarily need code, but an idea of how to make it work, so any ideas are welcome.

 

The table:

aNAYp.png

Column Descriptions:

id      - The unique id

label    - The text to display

link    - The link to be used

relation - I cannot remember why I wanted that... just disregard it

parent  - The parent item's id (0 for no parent)

sort    - A sort number for the item (ascending)

active  - 0 for false, 1 for true (not implemented yet, will add a WHERE `active` = 1 into the sql later)

depth    - How many parent items there are

 

Now, here's what it has to do (the class):

[*]Grab items from the database (sorted by depth, parent, and sort)

[*]Place the children in a child array of the parents (or however it can be sorted)

[*]Implode the array and turn it into an html menu with the below structure

 

Menu HTML Structure

<div id="menu">
  <ul>
    <li><h2>Level 1 A</h2>
      <ul>
        <li><a href="?r=level2/a">Level 2 A</a>
          <ul>
            <li><a href="?r=level3/a">Level 3 A</a></li>
            <li><a href="?r=level3/b">Level 3 B</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li><a href="?r=level1/b"><h2>Level 1 B</h2></a></li>
  </ul>
</div>

 

And here is the code I have so far, but I can't figure out how to get the children into the parent array, or at least sort it so that I can achieve the above HTML structure.

 

Thank you in advance for your help, and as I said above, I don't necessarily need code, but an idea of how to make it work, so any ideas are welcome.

Link to comment
Share on other sites

It seems as if you're using short-tags, r u sure your ini.config recognizes that? Besides ur sql query has to prefectly draw a uniform and persistent data from the base. U should check this out too...

I just used a short tag for the links because I didn't want to write out a full url for the example. The sql is written to draw uniform and persistent data from the database, but I forgot to include it.

<?php
/**
* Menu Class
*
* This file is used to create a dynamic menu based on the user's permissions and status
* @author Max Udaskin <max.udaskin@gmail.com>
* @version 1.0
* @package navigation
*/

/**
* @ignore
*/
if(!defined('ALLOW_ACCESS')) { // Do not allow the file to be accessed by itself
    die('Restricted File.');
}

require_once("Database.php");

class Menu
{
    protected $login;
    protected $all_rows;
    protected $menu_items;
    protected $html = NULL;

    /**
     * The constructor
     * @param Login $login
     */
    function _construct()
    {
    }

    /**
     * Get All Items
     * Retrieves all database menu items
     */
    private function getAllItems()
    {
        $sql = 'SELECT * FROM `menu` ORDER BY `depth` ASC, `parent` ASC, `sort` ASC';
        $database = new Database('default');
        $database->connect();
        $database->query($sql);
        $query = $database->getLastQuery();

        while($row = mysql_fetch_array($query))
        {
            $this->all_rows[] = $row;
        }
    }
    /*
     * Selects the menu items that are appropriate for the user
     */
    private function chooseMenuItems()
    {
        $this->menu_items = $this->all_rows;
    }

    /**
     * Formats the menu items for the HTML output
     */
    private function formatMenuItems()
    {
        $menu = array();
        $menu_imploded = '';
        
        for($i = 0; $i < count($this->menu_items); $i++) {
            if($this->menu_items[$i]['parent'] == 0) {
                $menu[] = $this->parseItem($this->menu_items[$i]);
            } else {
                $parent = $this->search($menu, $this->menu_items[$i]['parent']);
                print_r($parent);
            }
        }

        $menu_imploded = $this->combineMultiArray('', $menu);
        
        echo '<div id="menu">';
        echo $menu_imploded;
        echo '</div>';
    }

    /**
     * Searches an array and it's sub arrays for a defined value ($for)
     * @param array $array
     * @param mixed $for
     */
    private function search($array, $for)
    {
        
    }

    /**
     * Gets the array item and returns it
     * @param array $arr The array to insert the child into
     * @param string $string The 
     * @param array $child
     */
    function insertIntoArray($arr, $string, $child)
    {
        preg_match_all('/\[([^\]]*)\]/', $string, $arr_matches, PREG_PATTERN_ORDER);

        $return = $arr;
        foreach($arr_matches[1] as $dimension)
        {
            $return = $return[$dimension];
        }

        return $return;
    }

    /**
     * Parses HTML for the item, as an array
     * @param array $item
     */
    private function parseItem($item)
    {
        if($item['parent'] == 0) {
            $h2_s = '<h2>';
            $h2_e = '</h2>';
        } else {
            $h2_s = '';
            $h2_e = '';
        }
        $return[0] = '<ul><li>' . $h2_s . '<a href="';
        $return[0] .= $item['link'] . '">';
        $return[0] .= $item['label'] . '</a>' . $h2_e;
        $return[1] = false; // Children
        $return[2] = '</li></ul>';
        $return['parent'] = $item['parent'];

        return $return;
    }

    /**
     * Puts all of the HTML in the array together
     */
    private function produceHtml()
    {
        $this->getAllItems();
        $this->chooseMenuItems();
        $this->formatMenuItems();
    }

    /**
     * Get HTML
     * @return string The HTML menu
     */
    public function getHtml()
    {
        $this->produceHtml();
        return $this->html;
    }
    
    /**
     * Combine Multi Array
     * Takes any array of any dimension and combines it into a single string
     * @param unknown_type $array
     */
    private function combineMultiArray($glue, $array)
    {   
        $return = '';
        foreach($array as $piece) {
            if(is_array($piece)) {
                $return .= $glue . $this->combineMultiArray($glue, $piece);
            }
            $return .= $glue . $piece;
        }
        
        return $return;
    }
}

 

Link to comment
Share on other sites

Exellcent code...I like the way u implement your class with a good constructor besides your array seems ok 2 me.. but

private function getAllItems()
    {
        $sql = 'SELECT * FROM `menu` ORDER BY `depth` ASC, `parent` ASC, `sort` ASC';//try and re-query this TROUBLE SPOT  may be
         $sql = 'SELECT * FROM `menu` where clause=$clause;//better yet specify with an existing valid variable eg, $_session
        $database = new Database('default');
        $database->connect();
        $database->query($sql);
        $query = $database->getLastQuery();

        while($row = mysql_fetch_array($query))
        {
            $this->all_rows[] = $row;
        }
    }

 

the select statement seems clumsy..I've corrected but modify that region as best suites you.

Link to comment
Share on other sites

I'm not quite sure what you mean when you say that the query is clumbsy?

 

It does exactly what I want it to do, and it's not going to have to change based on a user or settings because the menu will be displayed in the same order every time.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.