All of my blog posts up to this point have been used to introduce myself and what I have done up-to now. This blog post is the first that is purely aimed at PHP development.
I first started with CodeIginiter about 2 months ago and I’ve spent a lot of my time reading their fantastic user guide. The only problem is that because the framework can do so much it can be very easy to miss some of the great features that it has. The tutorials that are provided in the user guide are only aimed at those just starting out and as such stays at a very basic level.
A feature that was added fairly recently (CodeIgniter 2.1.0) is Migrations. This is a useful Class that allows for you to create and manage your database structure through your code. Migrations aren’t themselves new (they came primarily from Ruby on Rails – an alternative programming languages which influences most of the PHP frameworks). Database migrations are a way of effectively versioning your database changes.
Lets use an example of a CMS product that is self hosted (wordpress for example). Over time the developers of that software will need to roll out database changes, however not everyone will be on the same version of the software. This means you need to be careful to ensure that only the database changes that are required are made when they upgrade their software. This is where the Migration class comes in. You would simply create a new migration versioning file, put in the changes that need to be made and then upgrade the version number in your configuration file.
Getting Started
To get started you simply need to open application/config/migrations.php and change:
$config['migration_enabled'] = FALSE;
to:
$config['migration_enabled'] = TRUE;
A bit lower down in this same file you will see the configuration property called migration_version. This is how the system knows what the curent database version should be for your site. When it recognises that you’re running on a lower version than this it will upgrade your database through all the steps leading up to this version. So once you add a migration you would increase this version number to match.
Next we need to create a directory in the application directory called migrations. This is where our database migrations will reside. Unfortunately there doesn’t seem to be a way to get CodeIgniter to generate these migration files for you (I’m not sure if Rails will do this?) so if you already have a database structure in place then it’ll take some work to get the inital structure reproduced in a file. Your version 1 migration file will basically match your existing/starting database structure.
Migration Files
You need to create a file inside this new directory and the naming format has to start with your version number followed by the name of your class (make it is descriptive of the changes that you are making i.e. your first one might be: initial_schema). My first migration file was called: 001_initial_schema.php and my next one could be 002_add_comments.
Your file would look something like this:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_Initial_schema extends CI_Migration {
public function up()
{
$this->dbforge->add_field(array(
'postid' => array(
'type' => 'INT',
'constraint' => 11,
'unsigned' => TRUE,
'auto_increment' => TRUE
),
'title' => array(
'type' => 'VARCHAR',
'constraint' => '100',
),
'content' => array(
'type' => 'TEXT',
'null' => TRUE,
),
));
$this->dbforge->create_table('posts');
}
public function down()
{
$this->dbforge->drop_table('posts');
}
}
You’ll notice that there are two functions (up and down) in this class. The up function is run when you upgrade to/past this version and likewise the down function is run if you downgrade your database (using the config file) below this version. Your down function will always do the reverse of what your up function does. Essentially restoring your database to the state that it was before that version was added. Also notice that the name of the class above matches the suggested file name I gave earlier (except for the word Migration), the code expects for the class to be named in this way and won’t work without it.
I won’t go into detail about the format to use for the field array when creating or modifying tables as CodeIgniter’s user guide on the Database Forge Class already explains this perfectly.
The only caveat I noticed is when you want to have a text or varchar field with a null default value. Normally in phpMyAdmin you would expect to tick the Null field and also set the default value to Null. However all you need to do here is specify null as TRUE which you should be able to see from my example above. If you try to define default as null then it will actually set the default as a blank string. I assume that this issue will get cleared up eventually but as long as you keep it in mind then it’s not hard to avoid.
Putting into Practice
Working in this way may seem a little clunky to start with but this functionality comes into it’s own when you have a product that you need to deploy to your customers. You don’t want to be giving them the SQL to enter into phpMyAdmin themselves. Instead this is something you can build directly into your install/upgrade scripts. You just need to load the library and call it’s current method (as below) and your database will automatically be upgraded/downgraded to the version defined in your config file.
load->library('migration');
$this->migration->current();
I would recommend building more into your script, in-case there are any errors etc but those two lines will do all the magic. So there you have it, you now have a version controlled database that can be rolled forwards/backwards whenever you want.
Is there a particular feature from CodeIgniter that you would like for me to delve into next? Have you used CodeIgniter or any other PHP framework before? Do you have any experience with Ruby on Rails? I’d love to hear from you so please Get in Touch or leave a comment below.
