How to develop a login and registration system in CodeIgniter 4

Let us develop a registration and login system in CodeIgniter 4 and MySQL database for the customers. There will be a simple home page with options for registration and login. Customers can submit a registration form. Once registration is successful, customer can login into the application. You will also learn form validation in CodeIgniter 4.

If you want to know how to install and configure CodeIgniter 4, you can read the topic How to Install and Test CodeIgniter4 in Your Local Computer

CodeIgniter Database Login FormFolders and Files

We will be using a folder named 'projects' in D:\ drive and installed CodeIgniter 4 in customer folder under projects directory. So, the root directory is D:/projects/customer.

We will have a Controller - Customer.php, Model - ModelCustomer.php and three views - home.php, login.php and signup.php under Views folder

Step 1 - Create a MySQL table to store customer details

We will use a table named 'customer' in MySQL database.

Table: customer

This table stores all customers who successfully completed the signup.

codeigniter login and registration table structure

Below are the columns in this table.

  1. id - Primary key and auto incremented id of the customer
  2. name - Name of the customer
  3. email - Email Id of the customer
  4. password - Password for login

customer.sql


CREATE TABLE `customer` (
  `id` int(11) NOT NULL,
  `name` varchar(100) NOT NULL,
  `email` varchar(100) NOT NULL,
  `password` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ALTER TABLE `customer`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `customer`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;

Step 2 - Write Model code (ModelCustomer.php)

We will simply select all rows from customer table. Below is the model code, keep ModelCustomer.php in app/Models folder.

app/Models/ModelCustomer.php


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

class ModelCustomer extends Model{
  protected $table = 'customer';
  protected $primaryKey = 'id'; 
  protected $allowedFields = ['name','email','password'];
}

$table is used to indicate that the model will primarily use this table. However, you can use other tables also in the query.

Step 3 - Write Controller code (Customer.php)

Our controller function will have an index() method, signup() method, login() method and logout() method. See the code below at the beginning of the controller:


<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use App\Models\ModelCustomer;

class Customer extends Controller {
	protected $model;
	public function __construct() {
		helper(['form', 'url']);
		$this->model = new ModelCustomer();
    }	

	public function index() {
		echo view('home');
	}
}

In the constructor method, form and url helpers are loaded. Then an instance of the model is created. Home page screen is given below:

codeigniter 4 login and registration source code

Let us now add the methods for Signup, Login and Logout in the controller.

Controller Method signup()

codeigniter 4 login and registration

When user clicks on Signup link in home page, this method is called. If the form is submitted, it does validation for the input fields using validation rules. If validation is fails, it reloads the view with val;idation error message. But if all fields are validated successfully, this method inserts the data in the table using the model. Let's see the code for signup() method.


public function signup() {
	$element = [];
	$element['succ_msg'] = "";
	$element['err_msg'] = "";
	if ($this->request->getMethod() === 'post') {
		$rules = [
			'name' => [
				'label' => 'Name',
				'rules' => 'trim|required',
			],
			'email' => [
				'label' => 'Email Id',
				'rules' => 'trim|required|valid_email|is_unique[customer.email]',
			],	
			'password' => [
				'label' => 'Password',
				'rules' => 'required',
			],
			'conf_pwd' => [
				'label' => 'Confirm Password',
				'rules' => 'required|matches[password]',
			]
		];

		$errors = [
			'name' =>[
				'required' => '{field} is required'
			],
			'email' => [
				'required' => '{field} is required',
				'valid_email' => 'This is not a valid email address',
				'is_unique' => 'This email id already registered'
			],
			'password' => [
				'required' => '{field} is required'
			],
			'conf_pwd' => [
				'required' => '{field} is required',
				'matches' => '{field} does not match with Password'
			],
		];
		if (!$this->validate($rules, $errors)) {
			echo view('signup',$element);
		}
		else {
		// validations are successful, go for signup
			$name = $this->request->getPost('name');
			$email = $this->request->getPost('email');
			$password = $this->request->getPost('password');
			$password = password_hash($password,PASSWORD_DEFAULT);
			$data = array('name'=>$name,  'email'=>$email, 'password'=>$password);
			$result = $this->model->save($data);
			if ($result){
				$msg = 'Signup successful, please login with your email id and password';
				$element['succ_msg'] = $msg;
			}
			else{
				$msg = "Error in Signup";
				$element['err_msg'] = $msg;
			}	
			echo view('signup',$element);
		}
	}
	else {	
		echo view('signup', $element);
	}
}  // end of method signup

For validating input fields, rules are defined using $rules array. For detail how to do form validation in CodeIgniter 4, you can read the topic How to Do Form Validation With Custom Rule in CodeIgniter4.

$this->model->save() method will insert the row in database table.

Controller Method login()

Method login() is called when user clicks on Login link in Home page. On successful login, it redirects the user to the home page where it shows a welcome message and a logout option, otherwise it reloads login view with the error message. Let's see the code:


<?php
public function login(){
	$session = session();

	if ($this->request->getMethod() === 'post') {
		$email = $this->request->getPost('email');
		$password = $this->request->getPost('password');
	    // validate fields
	    $rules = [
			'email' => [
				'label' =>'Email Id',
				'rules' => 'trim|required'
			],
			'password' => [
				'label' => 'Password', 
				'rules' => 'required',
			]
		];
		$errors = [
			'email' => [
				'required' => '{field} is required',
			],
			'password' => [
				'required' => '{field} is required'
			],
		];

		if (!$this->validate($rules, $errors)) {
			// validation not passed, so load the form again
		    echo view('login');
			} 
		else {
			$result = $this->model->where('email', $email)->first();
			if($result){
				$pass = $result['password'];
				$verify_pass = password_verify($password, $pass);
				if ($verify_pass) {
					$sess_array = [
						'email' => $result['email'],
						'name' => $result['name'],
					];
					$session->set($sess_array);
					return redirect()->to('/customer');
				}
				else {
					$session->setFlashdata('msg', 'Invalid password entered');
					echo view('login');
				}
			}
			else {
					$session->setFlashdata('msg', 'Email Id not registered');
					echo view('login');
				}
			}
		}
		else {
		echo view('login');
	}
}  // end of method login

It uses an array to store name and email in the session, so that name and email can be used anywhere in the application.

Controller Method logout()

Method logout() deletes the session and redirects the user to the home page. See below:


public function logout() {
	$session = session();
  	$session ->destroy();
  	return redirect()->to('/customer');
	}

So, these were our controller methods, now let's see the Views in next step.

Step 4 - Write Views (home.php, signup.php, login.php)

There will be three views for home page, signup page and login page. Additionally, there will be a custom css file and a small piece of JavaScripts for showing/hiding password in login page. Let us take a look at them one by one.

View for Home Page

Our home page is simple, it just displays two links, one for signup and other for login if customer is not logged in. But when customer is logged in, it will display welcome message with the name of the customer and a logout link. Below are the screens for before login and after login:

Before Login

login in codeigniter with database

After Login

login and registration form in codeigniter

app/Views/home.php


<!DOCTYPE html>
<html lang="en">
<head>
  <title>Customer Signup & Login</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>
    <?php $session = session();?>
    <div class="container">
        <h1>You are at Home Page </h1>
        <div class="welcome-user">
           <?php if ($session->get('name')) { ?>
              <h2>  <?php echo "Welcome ".$session->get('name');?></h2>
                <a class="user" href="/logout">Logout</a>
            <?php } else { ?>
                <a id = "signup"  href="/signup">Signup</a>
                <a class="user" id = "login"  href="/login">Login</a>
            <?php } ?>
        </div>
    </div>
</body>
</html>

View for Signup Page

Signup page will display a form for the customer to fill and submit. It has name, email id, password and confirm password fields along with a submit button.

app/Views/signup.php


<!DOCTYPE html>
<html lang="en">
<head>
  <title>Customer Signup</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>Customer Signup</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 = "/customer/signup" 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"><?= $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"><?= $validation->getError('email');?> </span>
      </div>
      <div class="form-group col-md-12">
        <label>Password</label>
        <input type = "password" name="password" id = "password" class="form-control" placeholder="Enter a Password">
       <span class="error"><?= $validation->getError('password');?> </span>
      </div>
      <div class="form-group col-md-12">
        <label>Confirm Password</label>
        <input type = "password" name="conf_pwd" id = "conf_pwd" class="form-control" placeholder="Enter Password again">
        <span class="error"><?= $validation->getError('conf_pwd');?> </span>
      </div>
      <div class="col-md-12 text-center">
        <input type ="submit" name="signup" class="btn btn-primary" value="Submit">
              
         <a href = "/customer" class="btn btn-danger" name="login">Cancel</a>
       </div>
     </form>
   </div>
 </body>
 </html>

Note that csrf_field() is added for CSRF protection and related error will be displayed using session()->getFlashdata('error'). To enable CSRF protection for post requests, update app/Config/Filters.php to add csrf for post in $methods property.


public $methods = ['post' => ['csrf'],];

View for Login Page

codeigniter 4 login and registration

Login page will have email_id and password as input fields. See below code:

app/Views/login.php


<!DOCTYPE html>
<html lang="en">
<head>
  <title>Customer Login</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">
<script src="/assets/js/scripts.js"></script>
</head>
<body>
	<div class="container">
		<h2>Customer Login</h2>
		<?php $validation = \Config\Services::validation(); ?>
		<form id ="frm" action = "/customer/login" method = "post">
			<?= csrf_field() ?>
			<p class="error">
			<?php if (session()->getFlashdata('msg')) {
				echo session()->getFlashdata('msg');
			}?>
		</p>
			<div class="form-group col-md-12">
				<label>Email Id</label>
				<input type = "text" class="form-control" name="email" id = "email" value="<?php echo set_value('email')?>" placeholder ="Enter your Email Id">
				 <span class="error"><?= $validation->getError('email');?> </span>
			</div>
			<div class="form-group col-md-12">
				<label>Password</label>
				<input type = "password" class="form-control" name="password" id = "password" placeholder ="Enter Password">
				<span class="error"><?= $validation->getError('password');?> </span>
			</div>
			<div class="form-group col-md-12 tgl-pwd">
				<input type="checkbox" class="check" onclick="togglePwd()">Show Password
			</div>
			<div class="form-group col-md-12 login-btn">
				<button type="submit" class="btn btn-primary" name="login">Login</button>      
				<a href = "/customer" class="btn btn-danger" name="login">Cancel</a>
			</div>
		</form>
	</div>
</body>
</html>

Here, we have included a JavaScript file scripts.js. We will use JavaScript function for the option "Show Password" which is added as checkbox. When user clicks on it, it calls a JavaScript function togglePwd() written in scripts.js.

Below is the code for togglePwd() function:

scripts.js


function togglePwd() {
  var pwd = document.getElementById("password");
  if (pwd.type === "password") 
    pwd.type = "text";
  else 
    pwd.type = "password";
}

This function changes the type of the password field in login page, from "password" to "text" and vice versa.

Let me give the stylesheet also I created for all these views.

style.css


* {box-sizing: border-box;
}
.container{
  min-height: 700px;
}
h1,h2 {
  margin-top: 50px;
  text-align: center;
}
.welcome-user {
  text-align: center;
  font-size: 20px;
}
.user{
  padding-left: 35px;
}
.login{
  text-align: center;
  font-size: 20px;
}
#frm {
  margin: 50px auto;
  padding-bottom: 30px;
  padding-top: 20px;
  border: 1px solid #09168d;
  border-radius: 7px;
  background: #fff;
  width: 47%;
  }
.tgl-pwd{
  padding: 0;
}
.check {
  width: 10%;
  height: 20px;
  }
label{
  font-weight: bold;
}
.login-btn{
  text-align: center;
}
p.error{
  color: red;
  text-align: center;
  font-size: 20px;
}
p.success{
  color: green;
  text-align: center;
  font-size: 20px;
}
span.error{
  color: red;
  text-align: left;
}

Step 5 - Update Configuration files and Test the Application

We will update below files in Config folder and also, we will have .env file updated in the root directory. See below:

Below is a section of app/Config/App.php, set $baseURL and $index Page as given below:


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

public $indexPage = '';

Update database setup file (app/Config/Database.php) for database name, userid and password.


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,
    ];

Update Routes (app/Config/Routes.php)


$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Customer');
$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('/', 'Customer::index');
$routes->get('/signup', 'Customer::signup');
$routes->get('/login', 'Customer::login');
$routes->get('/logout', 'Customer::logout');

Update .env to set the environment as development. This file is in root directory.

Copy of env to .env. Update the environment from production to development as below:


# CI_ENVIRONMENT = production
CI_ENVIRONMENT = development

Test the Application

You can test the application using built-in PHP server. In the command prompt from then project root run php spark serve. This will start the server in port 8080.

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

Click on Signup and do a successful signup. Then using the email and password as given during signup, try to login. You should be able to login successfully and see the message displayed on the screen with the name and logout link.

Signup and Login in Codeigniter 4Conclusion

Developing Registration and Login forms can help you understand CodeIgniter 4 if you have just started working with it. We have done form validation, used session library and used database select/insert. I hope this will help you in your project development.