Form Validation with Custom Rules in CodeIgniter 4

CodeIgniter 4 form validation can be done using built-in validation rules as well as by creating custom validation rules. In this topic, we will create a registration form and validate the form data when the user submits this form. In case validation fails, we will display an error message. We will also use callback validation in this example by creating custom rules.

We will assume you have already got CodeIgniter 4 installed in your project root. All you have to do is run the below command from the command line. For our example, we installed it in D:/projects.


 composer create-project codeigniter4/appstarter form

It creates a folder named 'form' in D:/projects and CodeIgniter 4 is installed in that folder.

If you want to know how to install and configure CodeIgniter 4, you can read the topic Install and Test CodeIgniter 4 on the XAMPP Server

Below is a screenshot of the registration page:

Codeigniter 4 Form Validation Tutorial with Example

Form Validation Example in Codeigniter 4 For Beginners	Folders and Files

As mentioned earlier, we have created a folder named 'projects' in D:\ drive and installed CodeIgniter 4 in the 'projects/form' folder. So, the project root directory is D:/projects/form.

We will have Controller - Candidate.php, Model - ModelCandidate.php and the view - register.php.

There is a custom validation rule for age checks. This is for age validation, as our form will accept only ages between 18 and 40, we need to validate the age entered by the user.

If you are using XAMPP and want to use the Apache Web Server instead of PHP built-in server, then you can install CodeIgniter 4 under xampp/htdocs/<your folder name>. In our case, this folder name is 'form'. I will show the necessary configuration changes and test the application for both web servers.

Create a MySQL table

Our table name is 'candidates' in MySQL database.

Table: candidates

It stores details of all the candidates who completed registration.

CodeIgniter 4 Form Validation Example

Below are the columns in this table.

  1. candidate_id - Primary key and auto incremented candidate id
  2. name - Name of the candidate
  3. address - Address of the candidate
  4. email_id - Email Id of the candidate
  5. age - Age of the candidate
  6. registration_dt - Date of Registration

candidates.sql


CREATE TABLE `candidates` (
  `candidate_id` int(11) NOT NULL,
  `name` varchar(100) NOT NULL,
  `address` varchar(200) NOT NULL,
  `email_id` varchar(100) NOT NULL,
  `age` smallint(6) NOT NULL,
  `registration_dt` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ALTER TABLE `candidates`
  ADD PRIMARY KEY (`candidate_id`);

ALTER TABLE `candidates`
  MODIFY `candidate_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;

Create the view for registration (register.php)

validation in codeigniter 4 with example

We will create a registration form with input fields Name, Email Id, Address and Age. This topic is more about form validation. So, let's take a look at the code first:

app/Views/register.php


<!DOCTYPE html>
<html lang="en">
<head>
  <title>Candidate Registration</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
  <link rel="stylesheet" href="/assets/css/style.css">
</head>
<body>
  <div class="container">
    <h2>Candidate Registration</h2>
    <p class="error "><?= $err_msg ?></p>
    <p class="success"><?= $succ_msg ?></p>
    <?php $validation = \Config\Services::validation(); ?>
    <?= session()->getFlashdata('error') ?>
    <form id ="frm" action = "register" method = "post">
      <?= csrf_field() ?>
      <div class="form-group col-md-12">
        <label>Name</label>
        <input type = "text" name="name" id = "name" class="form-control" maxlength="100" value="<?php echo set_value('name');?>" placeholder="Enter Your Name">
        <span class="error"><?= esc($validation->getError('name'));?> </span>
      </div>
      <div class="form-group col-md-12">
        <label>Email Id</label>
        <input type = "text" name="email" id = "email" class="form-control"  maxlength="100" value="<?php echo set_value('email');?>" placeholder="Enter Your Email">
        <span class="error"><?= esc($validation->getError('email'));?> </span>
      </div>
      <div class="form-group col-md-12">
        <label>Address</label>
            <textarea name="addr" id = "addr" class="form-control" maxlength="200" placeholder="Enter Your Address" ><?php echo set_value('addr');?></textarea>
       <span class="error"><?= esc($validation->getError('addr'));?> </span>
      </div>
      <div class="form-group col-md-12">
        <label>Age <small>(Must be between 18 and 40 only)</small></label>
        <input type = "number" name="age" id = "age" class="form-control" value="<?php echo set_value('age');?>" placeholder="Enter Your Age in Years">
        <span class="error"><?= esc($validation->getError('age'));?> </span>
      </div>
      <div class="col-md-12 text-center">
        <input type ="submit" name="signup" class="btn btn-primary" value="Submit">
       </div>
     </form>
   </div>
 </body>
 </html>

You can see in line 15, we have used $validation = \Config\Services::validation(), this will load the validation settings with rulesets that we can use in our validation. For each input field, an error message will be displayed in case validation fails for that field. Once the form is submitted register() method of the Candidate controller is called.

Write Controller code (Candidate.php)

The controller will have an index() method to display the register page and a register() method to process the submitted data. We will use the model ModelCandidate.php, so, we need to create an instance of the model. See the below code at the beginning of the controller:


protected $model;
protected $uri;
protected $validation;
public function __construct() {
  helper(['form', 'url']);
  $this->uri = service('uri');
  $this->validation = service('validation');
  $this->model = new ModelCandidate();
  }

public function index() {
  $element['succ_msg'] = "";
  $element['err_msg'] = "";
  echo view('register',$element);
  }

In the construct method, the 'form' and the 'url' helpers are loaded. 'uri' and 'validation' services are also loaded. Then an instance of the model is created. index() method is executed by default in a controller. In this method, it loads the view to display the registration form.

Controller Method register()

In this method, we will do all the validations for the various input fields in the form.

If the form is submitted, it validates the input fields using validation rules. If validation fails, it reloads the view with an error message displayed. But if all fields are validated successfully, this method inserts the data in the table using the model. Let's see the code for register() method.


if ($this->request->getMethod() === 'post') {
			$rules = [
				'name' => [
					'label' => 'Name',
					'rules' => 'trim|required',
				],
				'email' => [
					'label' => 'Email Id',
					'rules' => 'trim|required|valid_email|is_unique[candidates.email_id]',
				],	
				'addr' => [
					'label' => 'Address',
					'rules' => 'required',
				],
				'age' => [
					'label' => 'Age',
					'rules' => 'required|ageCheck'
				]
			];

			$errors = [
				'name' =>[
					'required' => 'You must enter a {field}'
				],
				'email' => [
					'required' => 'You must enter an {field}',
					'valid_email' => '{value} is not a valid email address',
					'is_unique' => '{value} already registered'
				],
				'addr' => [
					'required' => 'You must enter an {field}'
				],
				'age' => [
					'required' => 'You must enter an {field}',
					'ageCheck' => '{field} must be between 18 and 40',
				],
			];
			if (!$this->validate($rules, $errors)) {
				echo view('register',$element);
			}
			else {
			// validations are successful, go for registration
				$name = $this->request->getPost('name');
				$email = $this->request->getPost('email');
				$addr = $this->request->getPost('addr');
				$age = $this->request->getPost('age');
				$data = array('name'=>$name, 'address'=>$addr, 'email_id'=>$email, 'age'=>$age);
				
				$result = $this->model->save($data);
				if ($result){
					$msg = 'Registration successful';
					$element['succ_msg'] = $msg;
				}
				else{
					$msg = "Error in Registration";
					$element['err_msg'] = $msg;
				}	
				echo view('register',$element);
			}
		}
		else {  // load the form
			echo view('register',$element);
		}

Just check for 'age' validation. We have used a custom rule 'ageCheck'. This is to validate the allowed range of valid ages. We will discuss how it is defined. $errors is for custom error messages in case validation fails.

If validation is successful, $this->model->save() method will insert the row into the database table and return true or false.

Age validation

For age validation, we need to create a custom validation method. See the code below in ProjectRules.php under app/CustomValidation. This is similar to the callback method used in CodeIgniter 3.


namespace App\CustomValidation;
class ProjectRules {
	public function ageCheck(string $str) {
      	if (!empty($str)){
      		if ((int) $str <18 || (int) $str >40) {
      			return false;
      		}
      		else
      			return true;
      	}
      	return false;
	}
}

It checks the value of the input if it falls between 18 and 40. If not, it returns false. Based on this, a validation error message is displayed in the form.

Write Model code (ModelCandidate.php)

Our model is very simple, it defines the table name and updatable columns.


<?php
namespace App\Models;
use CodeIgniter\Model;


class ModelCandidate extends Model{
  protected $table = 'candidates';
  protected $allowedFields = ['name','email_id','address','age', 'registration_dt'];
}

Stylesheet for all these views.

style.css


h2{
	text-align: center;
	margin-top: 50px;
}

p.success{
  text-align: center;
  color:green;
  font-size: 20px;
}
p.error{
  text-align: center;
  color:red;
  font-size: 20px;
}

.error{
  color:red;
  min-height: 20px;
  font-size: 17px;
}

label{
	font-weight: bold;
}
 #frm {
  margin: 5px auto;
  padding-top: 21px;
  padding-bottom: 40px;
  border: 1px solid #09168d;
  border-radius: 7px;
  background: #fff;
  width: 47%;
}
textarea.form-control{
	resize: none !important;
	height: 100px !important;
}

Update Configuration files and Test the Application

We will update a few setup files under the Config folder and update .env file in the root directory.

  1. Update config file (app/Config/App.php) for $baseURL and $index
    
    public $baseURL = 'http://localhost:8080/';
    public $indexPage = '';
    
  2. Update database setup file (app/Config/Database.php). We are using "demo" database here. Update $default as below:
    
    public $default = [
            'DSN'      => '',
            'hostname' => 'localhost',
            'username' => 'root',
            'password' => '',
            'database' => 'demo',
            'DBDriver' => 'MySQLi',
            'DBPrefix' => '',
            'pConnect' => false,
            'DBDebug'  => (ENVIRONMENT !== 'production'),
            'charset'  => 'utf8',
            'DBCollat' => 'utf8_general_ci',
            'swapPre'  => '',
            'encrypt'  => false,
            'compress' => false,
            'strictOn' => false,
            'failover' => [],
            'port'     => 3306,
        ];
    
  3. Update Routes file (app/Config/Routes.php) as below:
    
    /*
     * --------------------------------------------------------------------
     * Router Setup
     * --------------------------------------------------------------------
     */
    $routes->setDefaultNamespace('App\Controllers');
    $routes->setDefaultController('Candidate');
    $routes->setDefaultMethod('index');
    $routes->setTranslateURIDashes(false);
    $routes->set404Override();
    $routes->setAutoRoute(true);
    
    /*
     * --------------------------------------------------------------------
     * Route Definitions
     * --------------------------------------------------------------------
     */
    
    // We get a performance increase by specifying the default
    // route since we don't have to scan directories.
    $routes->get('/', 'Candidate::index');
    $routes->get('/register', 'Candidate::register');
    $routes->post('/register', 'Candidate::register');
    
  4. Update .env to set the environment to development. This file is in root directory.

    
    # CI_ENVIRONMENT = production
    CI_ENVIRONMENT = development
    

Test the Application

You can test the application using built-in PHP server or you can use the Apache web server if you are using XAMPP.

Test using PHP built-in server

Open the command prompt and go to your CI4 project root. In my case, it is D:/projects/form. Then type php spark serve and enter. This will start the server in port 8080.

custom validation codeigniter 4

Run http://localhost:8080/ in the browser. This will open the home page.

validation error in codeigniter 4

Test the validation for all the fields. Try to submit an incomplete form. You should see the proper validation messages.

Test using Apache web server

If you are using XAMPP make sure your root folder is xampp/htdocs/form, i.e., you have to install CI4 in this folder. Open httpd-vhosts.conf file in Notepad from xampp\apache\conf\extra folder. Add the below line at the end of it.

DocumentRoot "D:/xampp/htdocs/form/public"

email validation in ci4

Save it and restart the Apache service from the XAMPP controller.

Now in app/Config/App.php, update base url as below:


public $baseURL = 'http://localhost/';

Open the browser and run http://localhost. You will see the page as displayed below:

custom validation codeigniter 4

Do the same testing described above.

That's it! Our development and testing are done for this CodeIgniter4 application.

Custom Validation Rule in CodeIgniter 4Conclusion

Form validation is an important part of any project development. We must ensure that correct and only desired data are stored in the system. I hope this gives you a starting point for form validation in CodeIgniter4.

Post a Comment

Save my Name and Email id for future comments