views:

121

answers:

2

Hola

I generate a menu from a database table using a function, and I've placed this in an extended base controller class:

<?php

class MY_Controller extends Controller {

    public function __construct()
    {
        parent::Controller();
    }

    public function category_menu()
    {
        $this->load->model('category_model', 'category');
        $categories = $this->category->get_categories();

        $menu ="<ul class=\"menu_body\" id=\"nav_categories\">\n";
        foreach($categories->result() as $row)
        {
            $menu .= "\t<li>" . anchor('listing/view' . $row->url, $row->name) . "</li>\n";
        }
        $menu .= "</ul>\n";

        return $menu;

    }
}

then naturally my controller looks like ~

<?php

class Site extends MY_Controller {

    function __construct()
    {
        parent::__construct();
    }

    function index()
    {
        $data['menu'] = $this->category_menu();
        $this->load->view('view', $data);
    }
}

this does work, but it seems inefficient to have to do this for ~every~ page/view?

Or is this just a limitation of CI/MVC and there's no other way of doing it.

thanks for any insight

+1  A: 

The better way of doing this is rendering content in views. You can have partial templates, you don't need to do string appending in the controller:

$categories = $this->category->get_categories();
$data['menu'] = $this->load->view('menu', array('data'=>$categories), TRUE);
$this->load->view('view', $data);

The TRUE in the call to view tell the function to return the rendered content and not put it into the buffer. You can then pass it to 'view'. You can also get the categories and pass them into the view 'view' and load the partial template from there.

Ken Struys
Thanks for the tip about not appending strings in the controller. But, does this still mean I need to do this for **each** "page". I was kind of hoping there may be a way of automating the populating of a $menu view. Kind of like having `$this->category_menu();` directly in the view, so when the view is called, the categories are populated. hope this makes sense
Ross
with a bit of experimenting I think I cracked it, thanks.
Ross
+1  A: 

If your menu entries won't be changing much you can probably cache the resulting array (serialized to file, to memcache, wherever) and use that to build your menu instead of querying the database on every pageload. Then you'll query the database only if the cache is not valid.

This way you should either expire the cache every few minutes so you get fresh data from the database, or make sure that whenever you update the menu structure from elsewhere (say, a CMS), you invalidate the cache (delete file, delete memcache key etc) so that next time you call category_menu() you get fresh data.

As a sidenote, Ken Struys raises a very valid point as well and you should consider it. The whole point of Controllers and Views is so that you can separate your code from your html.

Fanis
very good point, hadn't considered that. The menu entries won't be updated frequently so this looks like a promising option. thanks.
Ross