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.

My Books

Tags
Tweets
Feeds
We Love
Powered by Squarespace

Entries in extending (1)

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?