Extending CodeIgniter’s Validation Library To Check For Unique Values
Updated November 4, 2008: This extension has been updated slightly to work with CI’s new form validation class, added with version 1.7.0. If you’re using an older version of CI you should still use the extension on this page. If you’re using 1.7.0 or later, you should check out the updated extension.
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:
Updated September 12, 2008: Made some changes based on suggestions from the super-helpful CodeIgniter community. Thanks guys!
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* MY_Validation Class
*
* Extends 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
*/
class MY_Validation extends CI_Validation {
function My_Validation()
{
parent::CI_Validation();
}
// --------------------------------------------------------------------
/**
* Unique
*
* @access public
* @param string
* @param field
* @return bool
*/
function unique($str, $field)
{
$CI =& get_instance();
list($table, $column) = split("\.", $field, 2);
$CI->validation->set_message('unique', 'The %s that you requested is unavailable.');
$query = $CI->db->query("SELECT COUNT(*) dupe FROM $table WHERE $column = '$str'");
$row = $query->row();
return ($row->dupe > 0) ? FALSE : TRUE;
}
}
?>
Save the above code as system/application/libraries/MY_Validation.php and you’re ready to go. You can now add the “unique” rule to your existing validation, like so:
$rules['username'] = "required|min_length[5]|unique[users.username]";
$rules['emailaddress'] = "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) = split("\.", $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->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(*) 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.

October 10th, 2008 at 10:35 am
I love the simplicity of your extension. Does the new class need to be loaded with $this->load->library? I followed your directions but did not see any affect. Any help? Thanks
October 10th, 2008 at 11:08 am
You need to load the base validation library (
$this->load->library('validation');) but you shouldn’t need to do anything special to load the extension as long as you name the file correctly. The extension should be saved as system/application/libraries/MY_Validation.php, unless you’ve changed the class extension prefix. You can find that in config.php. It’s set to “MY_” by default. Hope you’re able to get it working.October 31st, 2008 at 11:34 am
Hi,
I find a different way to set the error message:
$language = $CI->config->item(‘language’);
$CI->validation->set_message($language,’unique’);
And set a variable in validator_lang file:
$lang['unique']= “The %s that you requested is unavailable.”;
It will make this validator more adaptable to other languages and make it usable for multi-language apps.
For the new form validation in 1.7.0 this code will work fine if you replace:
MY_Validation with MY_Form_validation,
CI_Validation with CI_Form_validation,
and $CI->validation with $CI->form_validation
Thanks for this tutorial.
Keep the good work.
October 31st, 2008 at 2:00 pm
Thanks libre. I’ve meant to look at the new form validation class but I haven’t had a chance yet. It sounds like it’s pretty easy to adapt.
November 3rd, 2008 at 11:24 am
A small fix in my comment.
Only with the changes I discribed above the form validation will not work with the rules in a config file.
It will need a $rules array parameter to run like this:
function My_Form_validation($rules = array())
{
parent::CI_Form_validation($rules);
}
December 16th, 2008 at 8:23 am
Hello, how unique function would work for an edit form? Because I need to send the id to check too.
December 16th, 2008 at 11:33 am
I’m not sure this is the right extension for checking the ID of something while editing, because I imagine in that case you would want the ID to match an existing record, and this extension will throw an error if it exists. Let me know if I’m not following you correctly.
You could add another function to this extension called “exists()” that works something like this:
I haven’t tested it, but it should work. It does the opposite of the unique function, returning an error if the id doesn’t exist.
January 17th, 2010 at 12:19 pm
good but the folling is much easier.you dont need to write the complete class but just add the following function in “system/libraries/Form_validation.php” file ……..
function unique($str, $field)
{
//$this->CI
//$CI =& get_instance();
list($table, $column) = split(“\.”, $field, 2);
//$this->CI->form_validation->set_message(‘unique’, ’sorry! user ‘.$str.’ doesnot exist.’);
$query = $this->CI->db->query(“SELECT COUNT(*) dupe FROM $table WHERE $column = ‘$str’”);
$row = $query->row();
return ($row->dupe == 0) ? FALSE : TRUE;
}
and then call the validation function from you form as follows…….
$this->form_validation->set_rules(‘user_name’, ‘Admin User Name’, ‘required|unique[prism_users.user_loginname]‘);
hows that plz rply thank……
January 17th, 2010 at 12:37 pm
I prefer to extend classes rather than modifying the originals because when codeigniter is updated the originals may be modified. When you extend a class you don’t have to keep track of which modifications you’ve made.
January 19th, 2010 at 3:05 pm
yes Sir,you are right ,I haven’t thought about this issue .thanx for your advice.you r really great…..