Monday, August 6, 2012

Allowing CodeIgniter models to have the same name as controller

Working with CodeIgniter is fun to me. I like it for being a leightweight, flexible and performant framework which was easy to learn and whose disigns fits well in my way of thinking.
Although one thing that annoys me is that models need to have different names than controllers. In many applications, a natural approach would yield the same name for the model and it's associated controller.
Lets look at a simple blogging app (blogging seems to be one of the "hello world" for webapps after all):
There would be one model Blog which can represent the blog in the database (having methods for getting information about a single blog or retrieving a list of entries).
In CodeIgniter, you put the following code into the application/models/blog.php file:

class Blog extends CI_Model {
   // Code for the model goes here
}


You might also want to implement a corresponding controller Blog, which allows to use URL like /blog/{id}. So you put the following into /application/controllers/blog.php

class Blog extends CI_Controller {
   public function show($id) {
     $this->load->model('blog');
     // Do something with the model
   }
}


This results in an error saying that class Blog is already defined (when CodeIgniter tries to load the model)


The obvious solution to this is to rename the model to, say, Blogmodel


I do not like this for the following reasons

  • It's longer to write. Instead of $this->blog you have to write $this->blogmodel. It's not much but it stills bothers me
  • It's inconsistent with the naming of libraries and controllers in CodeIgniter, which don't need any specific suffixes
  • There's a feature in the Loader class to rename models when loading, so you could do $this->load->model('blogmodel','blog') to use it as $this->blog, but this doesn't work with autoloading.
  • Finally, it's simply not necessary. Models and controllers live in a different namespace in CodeIgniter: There is only one controller (returned by the get_instance() function or referenced by $this) active. Models are loaded as instance variables into this controller object (and are referenced by $this->modelname). So there cannot be a conflict.

So I did a small hack in the Loader class, inserting the following lines into the CI_Loader::model() method:

$model = ucfirst($model);

// Insert these lines
if (class_exists($model . '_model'))
  $model = $model . '_model';
//

$CI->$name = new $model();

I still have to declare my model class with a suffix like

class Blog_model extends CI_Model {
}

but I put it in a file named /application/models/blog.php and use it like

$this->load->model('blog');
$this->blog->do_something();






No comments:

Post a Comment