Welcome Guest, Not a member yet? Register   Sign In
Multi level menu from database (parent->child)
#1

[eluser]JimmyJ[/eluser]
Awe, I don't know how long I've been at this now. If someone can tell me what I'm doing wrong I'll bake some cookies.

Anyway, I have a database
Code:
--
-- Table structure for table `content_menus`
--

DROP TABLE IF EXISTS `content_menus`;
CREATE TABLE IF NOT EXISTS `content_menus` (
  `menu_id` int(11) NOT NULL AUTO_INCREMENT,
  `content_id` int(11) NOT NULL,
  `content_menu_title` varchar(255) NOT NULL,
  `menu_position` bigint(20) NOT NULL,
  `parent` int(11) NOT NULL,
  PRIMARY KEY (`menu_id`),
  UNIQUE KEY `content_menu_id` (`menu_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=51 ;

--
-- Dumping data for table `content_menus`
--

INSERT INTO `content_menus` (`menu_id`, `content_id`, `content_menu_title`, `menu_position`, `parent`) VALUES
(3, 1, 'Home', 0, 1),
(45, 2, 'Services', 1, 1),
(5, 3, 'Clients', 2, 1),
(6, 4, 'Portfolio', 3, 1),
(7, 5, 'Blog', 4, 1),
(8, 14, 'Web Design', 1, 2),
(9, 15, 'Web Design Scotland', 0, 8),
(2, 0, 'Footer Menu', 2, 0),
(12, 6, 'Contact', 5, 1),
(31, 38, 'Web Design', 0, 4),
(1, 0, 'Main Menu', 1, 0),
(43, 39, 'Web Development', 1, 45),
(38, 42, 'Internet Marketing', 3, 45),
(40, 43, 'Web Design', 0, 45),
(46, 44, 'SEO', 2, 45),
(50, 49, 'HTML', 0, 40),
(47, 45, 'Web Design Wales', 1, 8);

And I have a Menu_model
Code:
<?php


class Menu_model extends CI_Model {
    
    function get_menu_structure(){
        //$this->db->where('parent',$parent);
        $this->db->order_by('menu_position','asc');
        $this->db->join('content', 'content.id = content_menus.content_id', 'left');
        $q=$this->db->get('content_menus', 'content');
        foreach($q->result() as $r){
            $data[$r->parent][] = $r->parent;
        }
        $menu=$this->build_menu($data);
        return $menu;
    }
    
    
    function build_menu($parent){
        static $i = 1;
        if (isset($parent)) {
            $menu = '<ul>';
            $i++;
            foreach ($parent as $r) {
                $child = $this->build_menu($r->menu_id);
                $menu .= '<li>';
                $menu .= '<a >url_key.'">'.$r->content_menu_title.'link</a>';
                if ($child) {
                    $i--;
                    $menu .= $child;
                }
                $menu .= '</li>';
            }
            $menu .= '</ul>';
            return $menu;
        } else {
            return false;
        }
    }


}

And a controller
Code:
function index()
    {
        
        
        $template = 'page';
        
        $main_menu = $this->menu_model->get_menu_structure();
        $data['main_menu'] = $main_menu;
        
        print_r ($main_menu); die();
        
        $data['content'] = '' . $template . '';
        //$this->output->cache(60);    
        $this->load->view('templates/master', $data);
        
        
        
    }

And a view with

Code:
&lt;?php echo $main_menu; ?&gt;


I'm getting the error:

Code:
A PHP Error was encountered

Severity: Notice

Message: Trying to get property of non-object

Filename: models/menu_model.php

Line Number: 25

A PHP Error was encountered

Severity: Notice

Message: Trying to get property of non-object

Filename: models/menu_model.php

Line Number: 27

etc etc

Can anyone tell me what I'm doing wrong? All I need is a simple recursive menu Sad
#2

[eluser]Twisted1919[/eluser]
At a moment, the
$q=$this->db->get('content_menus', 'content');
will return false, therefore the call
foreach($q->result() as $r){
$data[$r->parent][] = $r->parent;
}
produces the error, because $q is not an object anymore .
#3

[eluser]JimmyJ[/eluser]
Why will it return false?

Am I not just selecting everything from the table content_menus and content?
#4

[eluser]JimmyJ[/eluser]
I've changed it to
Code:
function get_menu_structure(){
        //$this->db->where('parent',$parent);
        $this->db->order_by('menu_position','asc');
        //$this->db->join('content', 'content.id = content_menus.content_id', 'left');
        $q=$this->db->get('content_menus');
        foreach($q->result() as $r){
            $data[$r->parent][] = $r;
        }
        $menu=$this->build_menu($data);
        return $menu;
    }


But it's still the same error.
#5

[eluser]Twisted1919[/eluser]
I got it a bit wrong, here is the deal:
you are populating an $data array that you are passing forward, you do it here:
Code:
foreach($q->result() as $r){
            $data[$r->parent][] = $r->parent;
        }
        $menu=$this->build_menu($data);
So, $data is an array getting only numerical keys, so if you print it out it'll look like:
Code:
Array(
  1 => Array(
          0=>1//parent
       ),
  2 => Array(
          0=>2//parent
       )
);

Then you pass this array to your build_menu($data) method, in which, you are doing
Code:
foreach ($parent as $r) {
          $child = $this->build_menu($r->menu_id);//BUM

As you can see, menu_id is not defined, actually $r itself cannot be an object because $parent is not an array of objects rather an array having only numerical values.

[Never mind the example]

Be sure that the query brings the menu_id key in .
#6

[eluser]JimmyJ[/eluser]
So from what I can gather, something like:
Code:
foreach($q->result() as $r){
            $data[$r->parent][] = $r->parent;
            $data[$r->content_menu_title][] = $r->content_menu_title;
            $data[$r->menu_id][] = $r->menu_id;
        }

Should work? Still seem to be getting the same error.
#7

[eluser]JimmyJ[/eluser]
Ok this seems to work - after digging around other posts.
Code:
&lt;?php


class Menu_model extends CI_Model {
    
    function get_menu_structure(){
        //$this->db->where('parent',$parent);
        $this->db->order_by('menu_position','asc');
        $this->db->select('*')->from('content_menus', 'content');
        $this->db->join('content', 'content.id = content_menus.content_id', 'left');
        $q=$this->db->get();
        foreach($q->result() as $r){
            
            $data[$r->parent][] = $r;
        }
        $menu=$this->build_menu($data, 1); // From Parent ID 1
        return $menu;
    }
    
    
    function build_menu($category, $parent){
        static $i = 1;
        $path = '';
        if (array_key_exists($parent, $category)) {
            $menu = '<ul>';
            $i++;
            foreach ($category[$parent] as $r) {
                $child = $this->build_menu($category, $r->menu_id);
                $path .= $r->url_key;
                $menu .= '<li>';
                $menu .= '<a href="/'.$path.'">'.$r->content_menu_title.'</a>';
                if ($child) {
                    $i--;
                    $menu .= $child;
                }
                $menu .= '</li>';
            }
            $menu .= '</ul>';
            return $menu;
        } else {
            return false;
        }
    }


}

Now I've got to work out how to create the path correctly. For example /services/web-design/html

Does anyone know how I'd go about this?




Theme © iAndrew 2016 - Forum software by © MyBB