About Jamie on Software

Jamie on Software is the online journal of web developer and writer Jamie Rumbelow.

Jamie likes books, guitars, programming, open source and food. He writes about these things too. This is where he puts the things he writes.

Tags
Tweets
Feeds
We Love
Powered by Squarespace
Friday
Mar182011

Extending CodeIgniter's Controller

This seems to be something that everybody's writing about - and by everybody, I mean Mark Huot and Greg Aker - so I thought I'd jump in and pick up where Mark left off. By extending the core CI_Controller class you can write a small layout library that lets you automatically load views into a layout.

class MY_Controller extends CI_Controller {
    protected $data;
    protected $view;
    protected $layout;

    /**
     * Remap the CI request, running the method
     * and loading the view
     */
    public function _remap($method, $arguments) {
        if (method_exists($this, $method)) {
            call_user_func_array(array($this, $method), array_slice($this->uri->rsegments, 2));
        } else {
            show_404(strtolower(get_class($this)).'/'.$method);
        }

        $this->_load_view();
    }

    /**
     * Load a view into a layout based on
     * controller and method name
     */
    private function _load_view() {
        // Back out if we've explicitly set the view to FALSE
        if ($this->view === FALSE) { return; }

        // Get or automatically set the view and layout name
        $view = ($this->view !== null) ? $this->view . '.php' : $this->router->directory . $this->router->class . '/' . $this->router->method . '.php';
        $layout = ($this->layout !== null) ? $this->layout . '.php' : 'layouts/application.php';

        // Load the view into the data
        $this->data['yield'] = $this->load->view($view, $this->data, TRUE);

        // Display the layout with the view
        $this->load->view($layout, $this->data);
    }
}

This instantly gives us a bunch of cool functionality:

  • Controller data can all be kept in $this->data, which keeps your controllers neat and allows you to pass view data through multiple methods
  • The view is automatically guessed based on the controller name and method name. You'll see precisely how this works in a moment.
  • The view is being loaded into a layout; defaulting to layouts/application.php.

One final thing to add is that all of these conventions can be overridden if we need to. If we don't want to load a view - we're outputting a file, or JSON or something else instead - we can simply set $this->view to FALSE. We can choose to load a specific view by setting $this->view to the view name, or load a different layout by setting $this->layout.

Here's how it looks in action:

class Gifts extends MY_Controller {

    /**
     * Automatically loads the gifts/index.php view
     */
    public function index() {
        $this->data['title'] = 'All Gifts';
        $this->data['gifts'] = $this->gift_model->get_all();
    } 

    /**
     * Loads the gifts/create.php view
     */
    public function create() {
        $this->data['title'] = 'New Gifts';
    }

    /**
     * Does not load a view
     */
    public function json() {
        $this->view = FALSE;
        die(json_encode($this->gift_model->get_all()));
    }
}

And then, in our views/layouts/application.php file we can echo the contents of the $yield variable, which will be automatically set as the contents of our view.

<h1><?= $title ?></h1>

<div id="contents">
    <?= $yield ?>
</div>

Cool, huh?

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments (4)

Great work!
I actually used this (your Base Controller from Bitbucket/GitHub) for a while.

March 18, 2011 | Unregistered CommenterJohan André

I've been using your MY_Controller for a while now in all of my projects. I love the autoloading of views and layouts. I'm having a hard time getting this to work with apps using modular separation (HMVC). Have you ever tried this with a modular codeigniter app?

March 22, 2011 | Unregistered CommenterAmmon Casey

How can you load the view in a base controller prior to hitting the actual controller, wouldn't this output the view before setting controller data?

April 16, 2011 | Unregistered Commentercurious

@curious The controller method is being called before the view is loaded, that's what the call_user_func_array is doing.

April 21, 2011 | Unregistered CommenterChris Schmitz

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>