Custom Validation Rule in CodeIgniter 4

Download the latest version of CodeIgniter 4 and unzip source code to new folder named LearnCodeIgniter4WithRealApps

Cut index.php and htaccess files in public folder to root folder of project

Open index.php in root folder find to line 16 replace path to Paths.php file as below:

$pathsPath = realpath(FCPATH . '/app/Config/Paths.php');

Open App.php in app/Config folder find to line 39 remove index.php string in $indexPage variable as below:

public $indexPage = '';

Open App.php file in app/Config folder. Set value for $baseURL variable as below:

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

Create new folder named Validation in app folder. In Validation folder create new PHP file named UsernameRules.php as below:

<?php

namespace App\Validation;

class UsernameRules
{
	public function usernameValidation(string $str, string $fields, array $data)
	{
		if ($data['username'] == 'abc') {
			return false;
		} else {
			return false;
		}
	}
}										

Open Validation.php file in app/Config folder and register custom validation as below:

<?php
	
use \App\Validation\UsernameRules;

public $ruleSets = [
  //... other rules
  UsernameRules::class // here we have registered
];										

Create new PHP file named Account.php in app/Controllers folder as below:

<?php

namespace App\Controllers;

class Account extends BaseController
{

	public function __construct()
	{
		helper(['url', 'form']);
	}

	public function index()
	{
		return view('account/index', [
			'validation' => \Config\Services::validation()
		]);
	}

	public function save()
	{
		$rules = [
			'username' => 'trim|required|min_length[3]|max_length[12]|usernameValidation[username]',
			'password' => 'trim|required|min_length[6]|max_length[20]|regex_match[/^((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})$/]',
			'repassword' => 'trim|required|min_length[3]|max_length[20]|matches[password]',
			'age' => 'trim|required|integer|greater_than[18]|less_than[120]',
			'email' => 'trim|required|valid_email',
			'website' => 'trim|valid_url'
		];

		$errors = [
			'username' => [
				'usernameValidation' => 'Username already exists'
			]
		];

		if (!$this->validate($rules, $errors)) {
			return view('account/index', [
				'validation' => \Config\Services::validation()
			]);
		} else {
			$request = \Config\Services::request();
			$data['account'] = $request->getPost();
			return view('account/success', $data);
		}
	}
}												

Create new folder named account in app/Views folder. In this folder, create new PHP file named as below:

Index View

In account folder, create new PHP file named index.php as below:

<html>

	<head>
		<title>Codeigniter 4 Form Validation</title>
	</head>

	<body>

		<h3>Register</h3>
		<ul>
			<?php foreach ($validation->getErrors() as $error) : ?>
				<li><?= $error ?></li>
			<?php endforeach ?>
		</ul>
		<form method="post" action="<?= site_url('account/save') ?>">
			<table cellpadding="2" cellspacing="2">
				<tr>
					<td>Username</td>
					<td>
						<input type="text" name="username" value="<?= set_value('username'); ?>" />
					</td>
					<td><?= $validation->getError('username') ?></td>
				</tr>
				<tr>
					<td>Password</td>
					<td>
						<input type="password" name="password" />
					</td>
					<td><?= $validation->getError('password') ?></td>
				</tr>
				<tr>
					<td>Re-Password</td>
					<td>
						<input type="password" name="repassword" />
					</td>
					<td><?= $validation->getError('repassword') ?></td>
				</tr>
				<tr>
					<td>Age</td>
					<td>
						<input type="text" name="age" />
					</td>
					<td><?= $validation->getError('age') ?></td>
				</tr>
				<tr>
					<td>Email</td>
					<td>
						<input type="text" name="email" />
					</td>
					<td><?= $validation->getError('email') ?></td>
				</tr>
				<tr>
					<td>Website</td>
					<td>
						<input type="text" name="website" />
					</td>
					<td><?= $validation->getError('website') ?></td>
				</tr>
				<tr>
					<td>&nbsp;</td>
					<td>
						<input type="submit" value="Save" />
					</td>
				</tr>
			</table>
		</form>

	</body>

</html>

Success View

In account folder, create new PHP file named success.php as below:

<html>

	<head>
		<title>Codeigniter 4 Form Validation</title>
	</head>

	<body>

		<h3>Account Info</h3>
		<table cellpadding="2" cellspacing="2" border="1">
			<tr>
				<td>Username</td>
				<td><?= $account['username'] ?></td>
			</tr>
			<tr>
				<td>Password</td>
				<td><?= $account['password'] ?></td>
			</tr>
			<tr>
				<td>Age</td>
				<td><?= $account['age'] ?></td>
			</tr>
			<tr>
				<td>Email</td>
				<td><?= $account['email'] ?></td>
			</tr>
			<tr>
				<td>Website</td>
				<td><?= $account['website'] ?></td>
			</tr>
		</table>

	</body>

</html>
			

Open Routes.php file in app/Config folder and define routes as below:

$routes->get('/', 'Account::index');
$routes->post('/account/save', 'Account::save');

Access index action in Account controller with following url: http://localhost:8091/LearnCodeIgniterWithRealApps/account/index

Output

Click Save button submit form to save action in Account controller with invalid data as below:

Click Save button submit form to save action in Account controller with valid data

Output