Extending CodeIgniter's Controller
Friday, March 18, 2011 at 7:32PM 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?
codeigniter,
extending 

