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, the 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 on 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 the 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 the Views folder

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;

Write Model code (ModelCustomer.php)

We will select all the rows from the 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.

Write Controller code (Customer.php)

Our controller 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');
	}
}

Load the form and url helpers in the constructor method. Then create an instance of the model. Home page screen is given below:

codeigniter 4 login and registration source code

We will add the methods for Signup, Login and Logout in the controller.

Controller Method signup()

codeigniter 4 login and registration

This method is called when the user clicks the Signup link on the home page. If the form is submitted, it validates the input fields. If the validation is successful, this method inserts the data into the database table. 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 <a href="/customer/login">login</a> 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 details on 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 into the database table.

Controller Method login()

Method login() is called when the user clicks on the Login link in the 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 the name and email in the session so that the 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.

Write Views (home.php, signup.php, login.php)

There will be three views for the home page, signup page and login page. Additionally, there will be a custom CSS file and a small piece of JavaScript for showing/hiding password in the 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 the other for login if the customer is not logged in. But when the customer is logged in, it will display a 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

The signup page will display a form for the customer to fill out and submit. It has the name, email id, password and confirm password fields and 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 the 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 the JavaScript function for the "Show Password" checkbox. When the 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 input type of the password field in the login page, from "password" to "text" and vice versa.

Let me give the stylesheet 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;
}

Update Configuration files and Test the Application

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 the built-in PHP server. Run php spark serve from the command prompt. 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 login using the email id and password as given during signup. 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.