How is Kohana different from CodeIgniter?

Click Upvote picture Click Upvote · Apr 17, 2011 · Viewed 9.1k times · Source

I've been using CodeIgniter for a long time, however lately I've been feeling the need to move to a more advanced/more OOP framework. Kohana seems to be an often recommended option, my question is, how exactly is Kohana different from CodeIgniter? A list of differences, particularly syntax differences, would be great.

Answer

Kemo picture Kemo · Apr 17, 2011

I'll be writing about Kohana 3.1 and main advantages I've seen over CodeIgniter 2 so far. Before Kohana 3.0 (year and a half ago), I used CodeIgniter, ZF, Symfony, Cake and tried many others (at the moment trying to do Yii only because I have to). I'm aware that many will spit on me for "being subjective". Go ahead.

Strict PHP 5.2

Kohana doesn't use any of the old code (meaning 2.x or CodeIgniter's) in the current version. It was totally rewritten to be fully object oriented and not to get in developer's way. Simply put, it feels natural to develop with it, like it's "the way" for PHP development.

This is a framework built "by the community, for the community", not for promotional purposes. And not by / for any community but a very leet one.

CodeIgniter stood still for way too long hanging on PHP4. Looking at the CI2s' source, I can't say they've fully moved on to PHP5 (let's say PHP 5.1 isn't really ... PHP 5). I've seen FuelPHP, which seems to be more like a mashup of CI2 with Kohana than a CI2 branch, though I have to say it definitely has potential.

HMVC

The main reason for Kohana to feel natural was born out of this pattern. The idea was to isolate every request to respect the pattern and it ended up with respecting the RFC 2616. Now you have a separate Response object for each Request, being able to reuse your code in a really neat way. Right now I'm working on a web service which is used with iPhone, Android and the web app. I can't describe what a privilege it is to call the API "on the inside". Raw example:

public function action_delete()
{
    $deleted = Request::factory('api/route')
        ->method(Request::DELETE)
        ->headers('Accept', 'text/html')
        ->execute();

    $this->response->body($deleted);
}

No handicaps

The team behind Kohana is dedicated to making the framework "the best it can be", not "everything it can be, because we .. have too much spare time". Each maintenance version is backward compatible with previous ones (e.g. 3.1.2 with 3.1.0), having all "major" changes wait for the minor versions (e.g. 3.1 isn't fully backward compatible with 3.0 "out of the box"). Previous minor versions are maintained for 6 months after the new one is released.

Exten(ding|sions)

Kohana's Cascading File System makes it extremely easy to extend existing components, or even the ones used by vendors. You can override everything on application / module level, without thinking about setting include / load paths manually anywhere (because all files and folders respect the same convention).

There is a whole bunch of modules, including Zend Framework. How's that? Simply put, you can even use ZF or any other library as a module inside of your Kohana app.

Besides all the community built modules, every Kohana installation includes a few which almost every application can benefit from:

  • Auth A simple, yet very powerful, authentication library. The module itself provides file auth driver only but enabling ORM gives us a more powerful one.

  • Cache Caching library with drivers for most popular caching techniques: APC, eAccelerator, file, memcache, SQLite, Wincache and Xcache. It is extremely easy to implement and change (even later changes of the cache driver are a one-liner).

  • Codebench If you need to benchmark some code, Codebench provides you a very simple way of doing it.

  • Database As everything else in Kohana, database module is also fully object-oriented and extendable. Comes with full MySQL and PDO support.

  • Image A simple module for easy image manipulation

  • ORM Default ORM based on ActiveRecord pattern, fully using the advantages of the Database module combined with PHP 5 magic methods. Besides this one you can use Jelly, Sprig, AutoModeler or any other custom PHP lib like Doctrine.

  • Unittest Kohana comes pre-packed with a great unit testing module. It's based on PHPUnit and fully "integrates" with your app, allowing you very easy TDD. Besides, the whole framework is unit tested.

  • Userguide Altough ignored by most developers, this module is one of the most powerful Kohanas' features. It provides the easiest possible way of tracking your API and the rest of Kohana documenation. Why wouldn't your application have its' own guide as well? You don't even have to think about it! As long as you keep track of comments / conventions in your code, this module will take care of the rest.

Code examples

Code is neater than CI's, having all classes autoloaded, though conventions are very similar.

Update example (using ORM):

public function action_update($post_id)
{
    $post   = ORM::factory('post', $post_id);
    $errors = array();

    if ($values = $this->request->post())
    {
        try
        {
            $post->values($values)->update();

            $this->request->redirect('post');
        }
        catch (ORM_Validation_Exception $e)
        {
            $errors += $e->errors();
        }
    }

    $this->template->content = View::factory('post/update', array(
        'post'  => $post,
        'errors'=> $errors,
    ));
}

In this example ORM is used to update a row, having update() call it's check() method to validate it's values. In case that validation fails, ORM_Validation_Exception is caught and the rest of try block isn't executed (i.e. redirection to /post). In the end, both the post object (Model_Post) and errors array are passed to View where they can be accessed directly.

Notice that all Database_Query_Builder methods are available inside of ORM, so you can also do 'fancy' stuff like:

ORM::factory('post')
    ->where('user_id','=',$user_id)
    ->join('users','INNER')
    ->on('users.id','=','posts.user_id')
    ->find_all();

Or (with relations):

$user = ORM::factory('user', $id);

foreach ($user->posts->find_all() as $post)
{
    foreach ($post->quotes->find_all() as $quote)
    {
        if ($quote->illegal())
        {
            $quote->delete();
        }
    }
}

Where illegal() can be some custom model-level method with fancy joins and stuff. I'm aware how inefficient this chunk looks like, it's just a code example, not "are JOINs better than additional queries" :)