johngirvin.com

John Girvin

This is the blog of John Girvin, a software engineer and web developer based in Belfast, Northern Ireland. He draws on over 14 years of hard won, real world experience of different projects, clients and working environments. Visit the rest of the site to find out more and get in touch.

John is currently working with the Art Technology Group (ATG), developing J2EE based, market leading e-commerce technology.

upgrading to codeigniter 1.7.0

November 19th, 2008 by John Girvin

The good folk over at EllisLab released a new version of their CodeIgniter open source PHP web application framework a few weeks ago, and I’ve now upgraded this site to use this new version (which you shouldn’t notice) and taken the opportunity to do some minor design and code cleanups (you will hardly notice).

This is a significant release for CodeIgniter and, despite the usual excellent migration guide that EllisLab supply, I ran into a few problems, mainly in relation to database access and queries.

Session user_data column

For those of us using a database to store user session information, CodeIgniter 1.7.0 brings changes that store custom session data in the database (instead of in cookies) as well. This
requires a new user_data column to be added to the sessions table in the database with a suggested definition as follows:

ALTER TABLE `ci_sessions` ADD `user_data` text NOT NULL

However, CodeIgniter 1.7.0 still tries to insert NULL user_data at times so defining the column as shown above will result in “Field ‘user_data’ doesn’t have a default value” database
errors being reported. MySQL does not allow default values for text type columns, so I had to modify the user_data column definition to allow null values, by simply removing the
NOT NULL clause:

ALTER TABLE `ci_sessions` ADD `user_data` text

MySQL Port Support

CodeIgniter 1.7.0 adds support for port numbers to its MySQL drivers, but, as I was upgrading from an existing installation, I just copied my application/config/database.php file over and therefore didn’t have a port number configured. This resulted in a port number of 0 being used (since PHP interprets an empty string as an integer zero) and the database connection failing with the error “Unable to connect to your database server using the provided settings“. Adding the following line to the configuration file fixed the problem:

$db['default']['port'] = "3306";

Problems with order_by random

Some functions of this site rely on the fetching database rows in a random order. In the code, this requires the use of the ActiveRecord order_by() function with a parameter of “random” as shown below:

$this->db->order_by('', 'random');

Unfortunately there seems to have been a bug introduced with CodeIgniter 1.7.0 that causes ActiveRecord to generate invalid SQL when the above function is called in that form. A database error “Unknown column ‘ RAND() LIMIT 1′ in ‘order clause’” is reported because of a spurious escape quote that is inserted into the generated SQL:

SELECT ... ORDER BY ` RAND() LIMIT 1

You can see the extra quotation mark just after ORDER BY. I developed my own quick fix for this problem, pending a bug fix release from EllisLab. In the mysqli_driver.php file found in system/database/drivers/mysqli/ (part of CodeIgniter itself), modify the _escape_identifiers() function by inserting the following lines at the start, around line 416:

if ($item == '')
{
    return $item;
}

The same fix (at a different line number!) can also be applied to the regular MySQL driver, mysql_driver.php in system/database/drivers/mysql.

Problems with order_by multiple fields

I’d been using the ActiveRecord order_by() function in the following form, to order records by multiple keys:

$this->db->order_by('date,title');

In versions of CodeIgniter previous to 1.7.0 this worked, but under the new version the error “Unknown column … in ‘order clause’” was reported. The SQL generated by ActiveRecord was of the form:

SELECT ... ORDER BY `date,title`

You can see that the comma separated sort columns have been added to the SQL as one identifier instead of individually. To fix this I simply changed my own database code to explode() the sort columns and call order_by separately for each one:

$this->db->order_by($this->order());

…was changed to:

foreach (explode(',', $this->order()) as $field) {
    $this->db->order_by($field);
}

A simple change, but something to be aware of.

On re-reading the CodeIgniter user guide, I don’t believe my original usage was actually supported. It was just blind luck it worked at all, but at least now I’m doing it right and there should be no problems with future versions. Fingers crossed!

New validation library

CodeIgniter 1.7.0 comes with a brand new form_validation library to help you validate your HTML form inputs. It replaces the old validation library, which remains in place for backward compatibility but is now considered deprecated. Changing your code to use the new library is fairly straightforward.

  • In your controller classes and views, use form_validation rather than validation as the library name:
    $this->load->library('form_validation');
    ...
    $this->form_validation->set_rules(...);
  • Instead of setting the “human readable” name of each form field separately with a call to set_fields(),
    set_rules() has a new signature that includes the human readable name in the call.

    $this->validation->set_fields(array(
        'name'      => 'Name',
        'email'     => 'Email Address'
    ));
    ...
    $this->validation->set_rules(array(
        'name'      => 'trim|xss_clean|required|max_length[255]|callback_name_check',
        'email'     => 'trim|xss_clean|strtolower|max_length[255]|valid_email'
    ));

    …becomes…

    $this->form_validation->set_rules(array(
        array(
            'field'   => 'name',
            'label'   => 'Name',
            'rules'   => 'trim|xss_clean|required|max_length[255]|callback_name_check'
        ),
        array(
            'field'   => 'email',
            'label'   => 'Email Address',
            'rules'   => 'trim|xss_clean|strtolower|max_length[255]|valid_email'
        )
    ));
  • Instead of accessing submitted validation values directly as dynamic instance variables of the validation library class, you now need to call the set_value() function to retrieve them. This applies equally to both fetching values in controller classes and repopulating form fields in views.
    $name = $this->validation->name;

    …becomes…

    $name = set_value('name');
  • Similarly, the list of validation errors is now retrieved by calling the validation_errors() function instead of reading directly from the error_string instance variable.

And you’re done

So there you have it – a new version of the core framework that underpins this and other sites I maintain. It’s a significant release and the migration has not been entirely painless, but hopefully it’s worth it and everything is working just dandy now under the new version. I also hope that, through the magic of Google, this little narrative will help those who are having problems of their own. Happy CodeIgniting!

John Girvin
Bookmark and Share

John Girvin is an experienced a software engineer and web developer based in Belfast, Northern Ireland. He draws on over 14 years of hard won, real world experience of different projects, clients and working environments.

John is currently working with the Art Technology Group (ATG), developing J2EE based, market leading e-commerce technology.

If you liked this article, why not subscribe to the RSS feed for more?

one comment on “upgrading to codeigniter 1.7.0”

Matt Fox
December 17 2008, 2:16 am

Thanks for the MySQL port support tip. I just upgraded my app to 1.7.0, and got the “Unable to connect to your database server using the provided settings” error. It’s nice when I can fix semi-obscure problems with a quick search.

share your thoughts?

design & content © 2008-2010 john girvin, all rights reserved.