Adding a validation for an already existing data in my CodeIgniter application doesn't work

I have a CodeIgniter web application that takes student information and saves them in a table named student. My table structure is this:

   name             varchar(30)
   roll             varchar(10)
   department       varchar(10)
   email            varchar(50)

   mobile           varchar(15)

In my application, I want to achieve the following behavior:

While inserting data, if roll data already exists, then a validation will appear next to the roll text field saying This roll number already exists. Please enter a new roll. That means, for duplicate entries of roll data, a validation will appear, and that data will not be inserted.

My controller is student.php, note that it contains a callback function and a validation rule:

 <?php
 if ( ! defined('BASEPATH')){ exit('No direct script access allowed');}
 class Student extends CI_Controller
 {
     function __construct()
     {
         parent::__construct();
         #$this->load->helper('url');
         $this->load->model('student_model');
         $this->load->library('form_validation');
         $this->load->library('session');
     }

     //Show all Students
     public function index()
     {
         $data['student_list'] = $this->student_model->get_all_students();
         $this->load->view('student_view', $data);
     }


     //Insert a student
     public function insert_student_db()
     {
         $udata['name'] = $this->input->post('name');
         $udata['roll'] = $this->input->post('roll');
         $udata['department'] = $this->input->post('department');
         $udata['email'] = $this->input->post('email');
         $udata['mobile'] = $this->input->post('mobile');

         $this->form_validation->set_rules('roll', 'Roll', 'callback_check_duplicate_roll');

        if($this->form_validation->run() == TRUE) 
        {
             $res = $this->student_model->insert_student($udata);
             if($res)
             {
                 header('location:'.base_url()."index.php/student/".$this->index());

             }

         }
         else
         {
             $this->session->set_flashdata('warning', 'Data already exists');
             redirect('/student/index/', 'refresh');
         }

    }

    // My callback function
    public function check_duplicate_roll($post_roll) 
    {
        return $this->student_model->checkDuplicateRoll($post_roll);
    }

}
?>

And my model is student_model.php, note that I've a method for checking duplicate roll data:

    <?php
    class Student_model extends CI_Model 
    {
         function __construct()
         {
              parent::__construct();
              $this->load->database();
         }  

         //To retrieve all students
         public function get_all_students()
         {
             $query = $this->db->get('student');
             return $query->result();
         }

         //Checking for duplicate roll
         public function checkDuplicateRoll($post_roll) 
         {
              $this->db->where('roll', $roll);
              $query = $this->db->get('student');
              $count_row = $query->num_rows();
              if ($count_row > 0) 
              {
                  return FALSE;
              } 
              else 
              {
                  return TRUE;
              }
         }


         //To add a new student to the database
         public function insert_student($data)
         {
             return $this->db->insert('student', $data);

         }

    }
    ?>

My view page - student_view.php:

  <!DOCTYPE html>
  <html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>My first site in CI</title>
  </head>
  <body>
  <h2>Student Information</h2>
  <form method="post" action="<?php echo base_url();?>index.php/student/insert_student_db">
  <table width="800" border="0">
  <tr>
  <th width="213" align="right" scope="row">Name:</th>
  <td width="161"><input type="text" name="name" size="60" /></td>
  </tr>
  <tr>
  <th align="right" scope="row">Roll:</th>
  <td><input type="text" name="roll" size="60" /></td>
  </tr>
  <tr>
  <th align="right" scope="row">Department:</th>
  <td>
  <select name="department">
  <?php 
       $sql = mysql_query("SELECT dept_name FROM department");
       while ($row = mysql_fetch_array($sql)){
             echo "<option value=\"{$row['dept_name']}\">" . $row['dept_name'] . "</option>";
       }
  ?></select>
  </td>
  </tr>
  <tr>
  <th align="right" scope="row">Email:</th>
  <td><input type="text" name="email" size="60" /></td>
  </tr>
  <tr>
  <th align="right" scope="row">Mobile:</th>
  <td><input type="text" name="mobile" size="60" /></td>
  </tr>
  <tr>
  <th align="right" scope="row">&nbsp;</th>
  <td><input type="submit" name="submit" value="Send" /></td>
  </tr>
  </table>
  </form>
  <table width="600" border="1" cellpadding="5">
  <tr>
  <th scope="col">Name</th>
  <th scope="col">Roll</th>
  <th scope="col">Department</th>
  <th scope="col">Email</th>
  <th scope="col">Mobile</th>
  </tr>
  <?php foreach ($student_list as $std_key){ ?>
  <tr>
  <td><?php echo $std_key->name; ?></td>
  <td><?php echo $std_key->roll; ?></td>
  <td><?php echo $std_key->department; ?></td>
  <td><?php echo $std_key->email; ?></td>
  <td><?php echo $std_key->mobile; ?></td>
  </tr>
  <?php }?>
  </table>
  </body>
  </html>

After I run my application in localhost and try to insert data, duplicate roll data is not inserted in my student table, that's fine, and my page is redirected to student_view.php. But the flash message doesn't show up. What is the problem? Is it a problem with my misplacement of flashdata? Or something else?

Note that this is the final, fully modified version of my question. I've edited this question 4 times ever since I first posted it, and because of all those edits, it looked ugly. So I've decided to trim my question according to the last updated version of my code. Please excuse the nature of this question and my inability to figure out the problem, cause I'm an absolute newby to CodeIgniter. Your kind help is going to help me understand CI and encourage me to carry on this journey.

Upvotes: 1

Views: 4869

Answers (2)

Gervs
Gervs

Reputation: 1397

student.php

public function checkDuplicateRoll($roll) {
    return $this->student_model->checkDuplicateRoll($roll);
}

If you define a callback function in a validation rule, the validator will call a function in the class where the validation rules are set. In this case Student controller.

Edit

Controller student.php:

public function insert_student_db() {
    // check if form is posted and assing variable to post data
    if (false !== $udata = $this->input->post()) {
        //unset the submit button
        unset($udata['submit']);
        $this->form_validation->set_rules('roll', 'Roll', 'callback_check_duplicate_roll');
        $this->form_validation->set_message('check_duplicate_roll', 'Role already exists');
        if ($this->form_validation->run()) {
            $this->student_model->insert_student($udata);
            redirect('index.php/student');
        }
        else {
            $this->load->helper('form');
            $this->load->view('studentForm');
        }
    }
}

//for some reason a callback function needs to be public
public function check_duplicate_roll($roll) {
    return $this->student_model->checkDuplicateRoll($roll) == false;
}

Model student_model.php

public function ckeckDuplicateRoll($roll) {
    $this->db->select('roll');
    $this->db->where('roll', $roll);
    $result = $this->db->get('student');
    return (bool) $result->num_rows();
}

Views in CodeIgniter

As a matter of fact it's MVC where talking about, but a view shouldn't contain any programming logic, except for some echoes (optional in an iteration), some minor calculations and some condtional statements. It's the controller that interacts with the model(s), and parses the data obtained to the view. In CI it's quite simple:

public function index() {
    $data = array('title' => 'My first CI site',
                  'header' => 'First attempt',
                  'departments' => $this->m_departments->getCollection()
                  );
    $this->load->view('student_view', $data);
}

CI runs $data through extract (core php function), so the keys becomes variables which contains the value. You can use these variables in the view:

// departments as example
<select name="department">
<?php
     foreach($departments as $row) {
         echo '<option value="' . $row['dept_name'] . '">' . $row['dept_name'] . '</option>';
     }
?>
</select>

Upvotes: 2

Kevin
Kevin

Reputation: 41885

In your present code, the validation is no where to be found. Initialize the library in your controller first:

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

And then when everything is okay, setting rules, etc.:

if($this->form_validation->run() !== false) {
    $res = $this->student_model->insert_student($udata);
}

For more info: https://ellislab.com/codeigniter/user-guide/libraries/form_validation.html#validationrules

EDIT:

Since you have your own validation, you could use that custom validation too:

$this->form_validation->set_rules('roll', 'Roll', 'callback_checkDuplicateRoll');

and in your custom funtion:

public function checkDuplicateRoll($post_roll) 
{
    $this->db->where('roll', $roll);
    $query = $this->db->get('student');
    $count_row = $query->num_rows();
    if ($count_row > 0) 
    {
        $this->form_validation->set_message('checkDuplicateRoll', 'This roll number already exists. Please enter a new roll.');
        return FALSE;
    } 
    else 
    {
        return TRUE;
    }
}

Upvotes: 2

Related Questions