Scott Nellé.com

Extending CodeIgniter’s Validation Library To Check For Unique Values

Updated August 29, 2010: I’ve updated this post to be compatible with the latest version of CodeIgniter. It’s currently compatible with 1.7.0 and later. If you are still running on an older version and want the old version of this code to match let me know; I will send it to you. When I updated the post I also reset the discussion since most of it was specific to the old code.

I’m working on small web application and I’m building it with CodeIgniter. Like most web applications, mine requires user registration and login. And like most login systems, mine is happiest if each user has a unique username. While the CodeIgniter validation library is pretty robust, it doesn’t come with a function for checking a value to see if it is unique or if it already exists in the database. Fortunately there are a couple of ways to remedy that.

The first way is outlined in the documentation for the validation library under the heading “Callbacks: Your own Validation Functions.” I tried this and it works well, but it requires you to write the functions in your controller or model. I thought that looked messy and I wanted something a little more streamlined, so I decided to extend the validation library with my own function. Extending CodeIgniter’s libraries is pretty easy. Here’s what I came up with–I’ll explain the important lines afterward:


<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
 * MY_Form_validation Class
 *
 * Extends Form_Validation library
 *
 * Adds one validation rule, "unique" and accepts a
 * parameter, the name of the table and column that
 * you are checking, specified in the forum table.column
 *
 * Note that this update should be used with the
 * form_validation library introduced in CI 1.7.0
 */
class MY_Form_validation extends CI_Form_validation {

	function My_Form_validation()
	{
	    parent::CI_Form_validation();
	}

	// --------------------------------------------------------------------

	/**
	 * Unique
	 *
	 * @access	public
	 * @param	string
	 * @param	field
	 * @return	bool
	 */
	function unique($str, $field)
	{
		$CI =& get_instance();
		list($table, $column) = explode('.', $field, 2);

		$CI->form_validation->set_message('unique', 'The %s that you requested is unavailable.');

		$query = $CI->db->query("SELECT COUNT(*) AS dupe FROM $table WHERE $column = '$str'");
		$row = $query->row();
		return ($row->dupe > 0) ? FALSE : TRUE;
	}
}
?>

Save the above code as system/application/libraries/MY_Form_validation.php and you’re ready to go. You can now add the “unique” rule to your existing validation, like so:


$this->form_validation->set_rules('username','User Name','required|min_length[5]|unique[users.username]');
$this->form_validation->set_rules('emailaddress','Email Address','required|valid_email|unique[users.email]');

This will check the values that entered for username and emailaddress to make sure they don’t already exist in the username and email fields in your table called users. The general format for the rule, then, is : unique[table.column]. This matches the SQL syntax for specifying fields when field names are ambiguous. Pretty cool.

So here’s what’s going on in each of the important lines.


$CI =& get_instance();

This creates a reference to the CodeIgniter super object and allows you to use it’s functions in your library. See the user guide for an explanation (under the heading “Utilizing CodeIgniter Resources within Your Library.”)


list($table, $column) = explode('.', $field, 2);

This line parses out the table name and column name. Note that it only returns 2 strings. This way you can specify something like unique[users.email.address], which would check the users table for a column called email.address. In mysql periods are allowed in field names but not table names, and the validation rule reflects that.


$CI->form_validation->set_message('unique', 'The %s that you requested is unavailable.');

This line sets the error message in case the value isn’t unique. %s will be replaced by the field description you enter in your validation fields. This would be better off in a language file, but for ease of use I’ve stuck it right in the library. CodeIgniter allows you to replace entire language files but not simply extend them with a single line. If that changes in the future I’ll revisit my decision.


$query = $CI->db->query("SELECT COUNT(*) AS dupe FROM $table WHERE $column = '$str'");
$row = $query->row();

Here’s where it checks the database to make sure your field is unique. In the query I assigned the row count to the keyword “dupe” (for duplicate.) I wanted to use “exists” or “match” but both are protected words in mysql. Oh well. Note the use of $CI->db->query instead of $this->db->query. That’s explained in the documentation link earlier in this post.


return ($row->dupe > 0) ? FALSE : TRUE;

Finally, this line returns the result of the validation check. In case you’re not accustomed to using ternary operators, here it is as an if/else:


if ($row->dupe > 0)
{
	return FALSE; // a match was found, validation fails
}
else
{
	return TRUE; // value is unique, validation passed
}

So there you have it. A quick extension to CodeIgniter’s validation library that allows you to check your database for unique values.

One Response to “Extending CodeIgniter’s Validation Library To Check For Unique Values”

  1. Casey Says:

    Best addition to the library ever. Thank you!

Leave a Reply