'is_unique for codeigniter form validation

I'm trying to figure out how I can use the is_unique rule from the Codeigniter form validation library in the following situation.

I'm trying to submit a edit user form and have the rule:

$this->form_validation->set_rules('user_name', 'User Name', 'required|trim|xss_clean|is_unique[users.user_name]');

What if other values in the form are being changed but this value stays the same. The form is going to see that this value already exists so how would I protect it from editing if this value isn't changed.



Solution 1:[1]

Using your code as an example, the is_unique validation rule works by looking for a field called user_name in your users database table. If the field with the same value exists it validates as false.

To make sure it runs only when the user submits a new value, you could check the posted value $this->input->post('user_name') against the value you pulled from the database to populate your form with. If they are the same, don't validate is_unique;

if($this->input->post('user_name') != $original_value) {
   $is_unique =  '|is_unique[users.user_name]'
} else {
   $is_unique =  ''
}

$this->form_validation->set_rules('user_name', 'User Name', 'required|trim|xss_clean'.$is_unique);

Solution 2:[2]

There's a better way to go around it, I think, still using CodeIgniters' validation library... Use edit_unique where you pass an extra parameter which is the id of the row you're editing.. See below.. I use it and works pretty fine for me.. hope it helps

$this->form_validation->set_rules('user_name', 'User Name', 'required|trim|xss_clean|edit_unique[users.user_name.'.$id.']');

Solution 3:[3]

$something = $this->input->post('something');

$this->form->validation->set_rules('something','Something','xss_clean|is_unique['tbl'.users]');

if($this->form_validation->run()== FALSE){

}

Solution 4:[4]

Simple Way

Just Change isset to is_object in system/libraries/form_validation.php

public function is_unique($str, $field)
{
    sscanf($field, '%[^.].%[^.]', $table, $field);
    return is_object($this->CI->db) //default isset
        ? ($this->CI->db->limit(1)->get_where($table, array($field => $str))->num_rows() === 0)
        : FALSE;
}

Solution 5:[5]

Here's an easy method that worked for me and uses well documented code (thanks to https://github.com/ivantcholakov for sharing it!). I found it referenced at https://github.com/bcit-ci/CodeIgniter/issues/3109#issuecomment-46346280

  1. Download https://github.com/ivantcholakov/starter-public-edition-3/blob/master/platform/application/libraries/MY_Form_validation.php (MIT licensed) and save it to your application at application\libraries\MY_Form_validation.php
  2. Delete these two lines from __construct():

    $this->CI->load->helper('checkbox'); $this->CI->load->helper('email');

  3. Delete all the functions except __construct() and unique().

  4. At the end of the __construct() method of your controller add this line:

    $this->load->library('form_validation');

  5. As per the documentation of the unique() method update your validation rule to add a "unique" rule like this (e.g. if you already have required and trim rules):

    …|required|unique[tablename.fieldname,tablename.(primaryKey-used-for-updates)]|trim...

Solution 6:[6]

Extend Form_validation.php library create class inside of application/libraries file name MY_Form_validation.php

<?php

class MY_Form_validation extends CI_Form_validation{
    protected $ci;
     public function __construct($config = array()){
                parent::__construct($config);
                $this->ci =& get_instance();
        }

                public function is_unique_update($str, $field){
                $explode=explode('@', $field);
                $field_name=$explode['0'];
                $field_id_key=$explode['1'];
                $field_id_value=$explode['2'];
                sscanf($field_name, '%[^.].%[^.]', $table, $field_name);

                 if(isset($this->ci->db)){
                        if($this->ci->db->limit(1)->get_where($table, array($field_name => $str,$field_id_key=>$field_id_value))->num_rows() === 0){
                             $this->ci->form_validation->set_message('is_unique_update', 'The {field} field must contain a unique value.');
                            return false;
                        }
                        return true;
                    }


            }
}  

Now in your controller

$this->form_validation->set_rules('user_name', 'User Name', 'required|trim|xss_clean|is_unique_update[users.user_name@id@'.$id.']');  

"@" I used for explode the string
where id is primary key of users table
and $id is the value of id. Now you can use this is_unique_update validation in any controller.

Solution 7:[7]

This question is very old but maybe some new people experience this problem and this is the solution for it. I bet your are using Modular Extensions (HMVC) and you have created a new library, MY_Form_validation. You did id for callbacks, so you have this line of code on your class in order to use callbacks:

$this->form_validation->CI =& $this;

Well, the solution to this is whenever you want to use "is_unique" you must delete this line of code "$this->form_validation->CI =& $this;" from the class. I have experienced this problem and i fix it this way, it works fine now.

If you realy want to use callbacks "$this->form_validation->CI =& $this;", then do it only on required "methods" / "functions" where you don't want to use is_unique.

Solution 8:[8]

This code helpful for unique validation to create and update function...

In controller

Add this form validation code in both create and update function

$this->form_validation->set_rules('order_no', 'Order no', 'required|callback_check_order_no');

Add this call back function in controller

function check_order_no($order_no) {        
        if($this->input->post('id'))
            $id = $this->input->post('id');
        else
            $id = '';
        $result = $this->Data_model->check_unique_order_no($id, $order_no);
        if($result == 0)
            $response = true;
        else {
            $this->form_validation->set_message('check_order_no', 'Order no already exist');
            $response = false;
        }
        return $response;
    }

In model

function check_unique_order_no($id = '', $order_no) {
        $this->db->where('order_no', $order_no);
        $this->db->where('status', "A");

        if($id) {
            $this->db->where_not_in('id', $id);
        }
        return $this->db->get('delivery_order')->num_rows();
    }

Solution 9:[9]

I'm using codeigniter3 and it shows me error when I check username on updating the value, is_unique is not designed to work with update scenario so using @Anthony Mutisya's answer, here is the complete solution

in your controller, add this line while validation username of the current user with the database

$this->form_validation->set_rules('user_name', 'User Name', 'required|trim|xss_clean|edit_unique[users.user_name.'.$id.']');

You can get that $id from your submited form.

Now, add the following function to /system/libraries/Form_Validation.php this file. System folder is present in your root of CodeIgniter3 folder.

/**
* edit_unique // for check on update value
*
* Check if the input value doesn't already exist
* in the specified database field.
*
* @param    string  $str
* @param    string  $field
* @return   bool
*/
function edit_unique($value, $params)  {
    $CI =& get_instance();
    $CI->load->database();
    $CI->form_validation->set_message('edit_unique', "Sorry, that %s is already being used.");
    
    list($table, $field, $current_id) = explode(".", $params);
    
    $query = $CI->db->select()->from($table)->where($field, $value)->limit(1)->get();
    
    if ($query->row() && $query->row()->id != $current_id)
    {
        return FALSE;
    } else {
        return TRUE;
    }
}

It works perfectly fine in my case

Solution 10:[10]

CodeIgniter 4 has already solution for that,

$validation->setRules([
    'email' => 'required|valid_email|is_unique[users.email,id,{id}]',
]);

$_POST = [
    'id' => 4,
    'email' => '[email protected]',
];

then the {id} placeholder would be replaced with the number 4, giving this revised rule:

$validation->setRules([
    'email' => 'required|valid_email|is_unique[users.email,id,4]',
]);

Official Documentation

Solution 11:[11]

we must have to add table name for is_unique

for Exp.

 is_unique[users.email]