CodeIgniter – Thanks For The Ride

Wow, how time flies!

It’s been about 2.5 years since I started using CodeIgniter, and 18 months since my last progress report. Even though I was clearly wrong on some things, I still get a laugh out of how pleasantly surprised I was at my first exposure to a real framework, and how (or more importantly why) I ever worked without one.

But alas; now seems like as good a time as ever to make what could be my final post on CodeIgniter :(.

worlds-smallest-violin 

I do not claim to be a PHP ninja by any stretch, but I feel obliged to try and help any up and coming developers who are asking the immortal question – which framework should I choose?  

2.5 years ago I was asking that question and my choice was CodeIgniter. Here is my interpretation of the bad, the good and the future for CodeIgniter.

The Bad

The Library and the API are stale and have cobwebs
You can certainly find some good CodeIgniter libraries around, but the fundamental problem is in the way they are implemented in CI. While all the cool kids and frameworks are using PHP 5.3+, framework agnostic composer packages and namespacing, CI is stuck with a library system (ignoring the getsparks initiative which never really  took off) that requires a lot of manual work to get rolling with. And nobody likes manual work.

Writing a native CodeIgniter library which significantly hooks into CI functionality in no way passes the ever-desirable “code reusability” test.

Stagnant development, tough decisions ahead
As pointed out in a post on Phil Sturgeon’s blog (a guy who seems to know his shit), CodeIgniter has some serious, if not insurmountable obstacles to overcome should it ever wish to catch up to the emerging PHP standards.

Significantly, to catch up to the cutting edge frameworks, CI would be unrecognisable from its current state (and hence, not backwards compatible).

Unit Testing
Doesn’t work. If you don’t realise the significance right now, in time you will – and if your vast code base is not readily testable, you will be doing these ones:

facepalm

The Good

It still does a decent job
CI still largely does a decent job of solving many common problems, and it’s well documented and supported. For plenty of developers, this is all that matters.

You can start using composer now
Whether you are building new apps with CI or you are maintaining old apps, start using composer now (I outline how easy this is here).  At least you can start getting into the practice of dependency management and using and developing project dependencies.

By studying many of the popular packages available you will also start to realise how top notch modern PHP code is written, and start to see some of the shortcomings in CodeIgniter.

The Future

CodeIgniter is here to stay – at least for now – and who knows, it might even get on the comeback trail if version 3.0 can really deliver. At the very least, it’s going to continue to solve problems for a lot of developers and be used in existing applications for years to come.

The problem for me is that it is a very long way from the cutting edge, and I see it as a slowly sinking ship. You have to scroll all the way to 24th August 2006 on the PHP release page to get to 5.1.6, which is the minimum requirement for the last stable release of CodeIgniter, 2.1.4.

Depending on your requirements, CI may very well be ok, but for the complex application I would definitely suggest you look at other frameworks, and like many have suggested, Laravel is a worthy modern successor to CodeIgniter and one that I am currently sinking my teeth into.

Perhaps “Developer13″ comment summed it up best in EllisLab’s post which proposes offloading the ownership of CodeIgniter – I couldn’t agree more.

Just put it to rest peacefully! It’s lived a good life.

Database Seeding in CodeIgniter

When developing web applications, have you found yourself registering test accounts, inserting test posts, comments or otherwise inserting data directly into your database, such that you are reliant on that data?  Are you using a clone of a production database, or worse yet, developing and testing in a production environment?

Your doing it wrong!

Database seeding as a concept means that not only can you build a viable database in a flash, but crucially you can reset the data anytime without consequence as you inevitably make a meal of the existing data during application development.

Save time – fake it

You are probably only attached to your development database because you’ve spent a lot of time generating all that data and getting it just right. But theres a better way – fake it! You (probably) don’t need “actual” data in your database, you need data that is representational of what your production data will look like.

So how do we seed a database using CodeIgniter? Read on for the big reveal.

Step 1. Get Composer

If you don’t have Composer, get Composer. Seriously. If you don’t know what Composer is, start learning – you’ll never look back. I won’t be going into the installation or usage of Composer itself.

Step 2. Add the Composer autoloader to CodeIgniter

Adding composer inside CodeIgniter is as easy as adding a couple of lines to your front controller, which by default is your index.php file. Scroll to the bottom of index.php and add the following:


/*
 * --------------------------------------------------------------------
 * LOAD THE COMPOSER AUTOLOAD FILE
 * --------------------------------------------------------------------
 */
include_once '../../vendor/autoload.php';

/*
 * --------------------------------------------------------------------
 * LOAD THE BOOTSTRAP FILE
 * --------------------------------------------------------------------
 *
 * And away we go...
 *
 */
require_once BASEPATH.'core/CodeIgniter.php';

/* End of file index.php */
/* Location: ./index.php */

Step 3: Get Faker

Faker is your new best friend (if it’s possibly to be friends with a software package), and it is going to do all the heavy lifting to generate fake data.

Besides Faker providing a large array of representational user data like usernames, names, email addresses, postal addresses and credit card numbers, it also comes packaged with versatile date helpers and even a cool fake (but real) imaging service, Lorem Pixel.

Add Faker into your composer.json file. You probably want it under “require-dev” as you won’t be using it in a production environment. Note that at the time of writing the “dev-master” branch was required due to an apparent tagging mishap on the repository causing the image provider to be unavailable.

{
    "require-dev": {
        "fzaninotto/Faker": "dev-master"
    }
}

Don’t forget to update composer.

composer update

Ok, now that we have Composer, Faker and CodeIgniter singing in harmony, it’s time to get faker than Steve Tylers face! (sorry)

Step 4: Start Faking

Here’s an example controller that first truncates the old user table, and then seeds new rows into an empty user table. It is assumed that your user table already exists.

Danger: This script will truncate your user table so DO NOT run it against your production database. You have been warned.

<?php

if (!defined('BASEPATH')) {
    exit('No direct script access allowed');
}

/**
 * App Class
 *
 * Stop talking and start faking!
 */
class App extends CI_Controller
{
    function __construct()
    {
        parent::__construct();

        // can only be called from the command line
        if (!$this->input->is_cli_request()) {
            exit('Direct access is not allowed');
        }

        // can only be run in the development environment
        if (ENVIRONMENT !== 'development') {
            exit('Wowsers! You don\'t want to do that!');
        }

        // initiate faker
        $this->faker = Faker\Factory::create();

        // load any required models
        $this->load->model('user_model');
    }

    /**
     * seed local database
     */
    function seed()
    {
        // purge existing data
        $this->_truncate_db();

        // seed users
        $this->_seed_users(25);

        // call more seeds here...
    }

    /**
     * seed users
     *
     * @param int $limit
     */
    function _seed_users($limit)
    {
        echo "seeding $limit users";

        // create a bunch of base buyer accounts
        for ($i = 0; $i < $limit; $i++) {
            echo ".";

            $data = array(
                'username' => $this->faker->unique()->userName, // get a unique nickname
                'password' => 'awesomepassword', // run this via your password hashing function
                'firstname' => $this->faker->firstName,
                'surname' => $this->faker->lastName,
                'address' => $this->faker->streetAddress,
                'city' => $this->faker->city,
                'state' => $this->faker->state,
                'country' => $this->faker->country,
                'postcode' => $this->faker->postcode,
                'email' => $this->faker->email,
                'email_verified' => mt_rand(0, 1) ? '0' : '1',
                'phone' => $this->faker->phoneNumber,
                'birthdate' => $this->faker->dateTimeThisCentury->format('Y-m-d H:i:s'),
                'registration_date' => $this->faker->dateTimeThisYear->format('Y-m-d H:i:s'),
                'ip_address' => mt_rand(0, 1) ? $this->faker->ipv4 : $this->faker->ipv6,
            );

            $this->user_model->insert($data);
        }

        echo PHP_EOL;
    }

    private function _truncate_db()
    {
        $this->user_model->truncate();
    }
}

You will notice a couple of checks at the top to make this script only accessible by the command line, and to restrict this script to the development environment only. If you prefer you can run this script from your browser, just comment out the command line check and run mysite.com/app/seed.

I prefer to run my scripts from the terminal, to run this script cd into your CodeIgniter folder and run:


stevethomas$  php index.php app seed

This should give you a decent foundation to start seeding your development database. The more up to date, representational and flexible your seeding process is, the faster you can rinse and repeat whether it be for testing or just when you’ve made a mess of your development database.

Further Reading