Login and Register in CodeIgniter 4

If you are also learning CodeIgniter right now then you are on the right place today. Let’s learn how we can create an authentication system in CodeIgniter 4. This is the latest version of CodeIgniter in which we are going to build login and register functionality in CodeIgniter.

CodeIgniter is a very basic framework as compare to Laravel. Because it won’t take much time to understand it. Let’s move on tutorial now.

Prerequisites

  1. You should have a basic knowledge of PHP
  2. You should have a basic knowledge of OOP’s too.
  3. Setup PHP with Local Server e.g. XAMPP OR WAMPP
  4. Ability to learn something

Install CodeIgniter

First thing that you have to do is to install the CodeIgniter because without that you can’t move forward. Use below command to install the 4 version of CodeIgniter. This is the latest version which I am using now. If you are working on any other version please do take a look at documentation first.

composer create-project codeigniter4/appstarter AuthSystem

Create View Files

Now, Let’s assume we have installed our project successfully and now we have to create three pages.

  1. login page
  2. Register page
  3. Dashboard page

Because these are the most important pages. Let me explain, First of all you will land of Login page to login and if not have credentials then you will register after register you will login and land on dashboard. So, this is the flow. Let’s learn how we can make it more better.

After doing this we will be able to create login and register in CodeIgniter successfully

In App directory we do have View directory in which we will create these files.

login page code

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>login</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>

<body>
    <div class="container">
        <div class="row d-flex align-items-center justify-content-center" style="min-height: 600px;">
            <div class="card">
                <div class="card-content">
                    <div class="card-body shadow">
                        <?php if (isset($_SESSION['success'])) { ?>
                            <div class="alert alert-success" role="alert">
                                <?php echo $_SESSION['success'];
                                unset($_SESSION['success']);
                                ?>
                            </div>
                        <?php } ?>
                        <div class="card-title">Login</div>
                        <form action="login/auth" method="POST" >
                            <div class="form-group">
                                <input type="email" placeholder="enter email.." class="form-control" name="email" required>
                            </div>
                            <div class="form-group">
                                <input type="password" placeholder="enter password.." class="form-control" name="password" required>
                            </div>
                            <div class="form-group">
                                <button class="btn btn-secondary shadow-sm">Login</button>
                                <a href="register">Do not have any account</a>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>

</html>

We will create login page first it look like as in the picture below.

login.php page

Now, we will create register page where a use can register and after that we will move to code functionality in which we will cover all the stuff related to model, view, controller etc..

Register page code

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Register</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">

</head>

<body>
    <div class="container">
        <div class="row d-flex align-items-center justify-content-center" style="min-height: 600px;">
            <div class="card">
                <div class="card-content">
                    <div class="card-body shadow">
                        <div class="card-title">Register</div>
                        <form action="register/auth" method="POST">
                            <?php
                            if (!empty($errors)) { ?>
                                <div class="alert alert-danger" role="alert">
                                    <ul>
                                        <?php foreach ($errors as $error) :
                                        ?>
                                            <li><?= esc($error) ?></li>
                                        <?php
                                        endforeach ?>
                                    </ul>
                                </div>
                            <?php } ?>
                            <?php if (isset($_SESSION['danger'])) { ?>
                                <div class="alert alert-danger" role="alert">
                                    <?php echo $_SESSION['danger'];
                                    unset($_SESSION['danger']);
                                    ?>
                                </div>
                            <?php } ?>
                            <div class="form-group">
                                <input type="text" placeholder="enter name.." class="form-control" name="uname" required>
                            </div>
                            <div class="form-group">
                                <input type="email" placeholder="enter email.." class="form-control" name="email" required>
                            </div>
                            <div class="form-group">
                                <input type="password" placeholder="enter password.." class="form-control" name="password" required>
                            </div>
                            <div class="form-group">
                                <button class="btn btn-info shadow-sm" type="submit" name="register">Register</button>
                                <a href="login">Already have an account</a>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>

</html>

After creating a register page you might have a same look of frontend as I do have. So, now let’s look at how register page will look like.

register.php page

Dashboard page code

    <!DOCTYPE html>
    <html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title><?= esc($title) ?></title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
    </head>

    <body>
        <div class="container">
            <div class="row d-flex align-items-center justify-content-center" style="min-height: 100vh;">
                <h3>Welcome <?= $_SESSION['name'] ?></h3>
                <br>
                <a href="/logout" class="btn btn-danger">Let me logout</a>

            </div>
        </div>
    </body>

    </html>

Read About MVC If You want

Almost in each framework these process follows. I mean each framework does have MVC structure. Model , View and Controller. In Model we do all the stuff related to getting data from database and interacting with the tables. Basically Model represents tables for each table. We do have separate Model. In the same way we do have View directory which means frontend. Basically in View we do store our html and the files that will be viewed on frontend. In Controller we all logic kind of stuff. For example getting data from model and playing with that data and transferring to view.

This is all about MVC. With the same flow we will build login and register in CodeIgniter

Establish Database Connection

Without database we are not able to do anything with Authentication. So, I have decided do it first. For this, we have to go to Config directory and in this we will have Database file in which you have put some database information and also have to create the database.

 public $default = [
        'DSN'      => '',
        'hostname' => 'localhost',
        'username' => 'root',
        'password' => '',
        'database' => 'blog',
        'DBDriver' => 'MySQLi',
        'DBPrefix' => '',
        'pConnect' => false,
        'DBDebug'  => (ENVIRONMENT !== 'production'),
        'charset'  => 'utf8',
        'DBCollat' => 'utf8_general_ci',
        'swapPre'  => '',
        'encrypt'  => false,
        'compress' => false,
        'strictOn' => false,
        'failover' => [],
        'port'     => 3306,
    ];

Make Migration

We are going to make migration because If you are using a framework and creating tables manually in database then this is not a good practice. let’s use migration for more consistency.

php spark make:migration addusers
<?php

namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class AddUsers extends Migration
{
    public function up()
    {
        $this->forge->addField([
            'id' => ['type' => 'INT', 'constraint' => 5, 'unsigned' => true, 'auto_increment' => true],
            'name' => ['type' => 'VARCHAR', 'constraint' => 200],
            'email' => ['type' => 'VARCHAR', 'constraint' => 200],
            'password' => ['type' => 'VARCHAR', 'constraint' => 200],
            'created_at' => ['type' => 'datetime'],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->createTable('users');
    }

    public function down()
    {
        $this->forge->dropTable('users');
    }
}
php spark migrate

Now, after following these four steps you will have a table in database called users. In which we will do all the stuff.

You don’t have to change anything just put information about hostname, username, password, and database.

Make Model

Now, we have to create the Model, So, that we can interact with created table in under standard.

php spark make:model User

Model has been created and now add some code to model.

<?php

namespace App\Models;

use CodeIgniter\Model;

class User extends Model
{
    protected $DBGroup          = 'default';
    protected $table            = 'users';
    protected $primaryKey       = 'id';
    protected $useAutoIncrement = true;
    protected $insertID         = 0;
    protected $returnType       = 'array';
    protected $useSoftDeletes   = false;
    protected $protectFields    = true;
    protected $allowedFields    = ['name', 'email', 'password'];

    // Dates
    protected $useTimestamps = false;
    protected $dateFormat    = 'datetime';
    protected $createdField  = 'created_at';
    protected $updatedField  = 'updated_at';
    protected $deletedField  = 'deleted_at';

    // Validation
    protected $validationRules      = [
        'uname' => 'required',
        'password' => 'required|min_length[10]',
        'email'    => 'required|valid_email',
    ];
    protected $validationMessages   = [
        'uname' => 'username required',
        'password' => 'password required',
        'email' => 'email required',
    ];
    protected $skipValidation       = false;
    protected $cleanValidationRules = true;

    // Callbacks
    protected $allowCallbacks = true;
    protected $beforeInsert   = [];
    protected $afterInsert    = [];
    protected $beforeUpdate   = [];
    protected $afterUpdate    = [];
    protected $beforeFind     = [];
    protected $afterFind      = [];
    protected $beforeDelete   = [];
    protected $afterDelete    = [];

    public function createUser($param = array())
    {
        $password = password_hash($param['password'], PASSWORD_BCRYPT);
        $data = ['name' => $param['name'], 'email' => $param['email'], 'password' => $password];
        $this->save($data);

        return true;
    }

    public function verifyUser($email, $password)
    {
        return $this->table($this->table)->where('email', $email)->get();
    }
}

When you will run the command to create the model you will have everything. But don’t forget to add the usable fields in $allowedFields. I have only created two functions first to register the user and second for check the user login details.

Create Controller File

Now, we have to create the controller to make some logics related to login and register functionality. We do have Controller directory in App directory. Create a controller via command , take enjoy of CLI also, don’t go very straight forward.

php spark make:controller AuthController

Edit AuthController File

Add some code to AuthController file to do all the logics for login and register. I’ll explain code below don’t forget to read.

<?php

namespace App\Controllers;

use App\Controllers\BaseController;
use App\Models\User;
use Config\Services;

class AuthController extends BaseController
{
    public function __construct()
    {

        $this->userModel = new \App\Models\User();
        $this->session = \Config\Services::session();
        if (isset($_SESSION['loggedIn'])) {
            return redirect()->to('/dashboard');
        } else {
            return redirect()->to('/login');
        }
    }
    public function index()
    {
        if (isset($_SESSION['loggedIn'])) {
            return redirect()->to('/dashboard');
        } else {
            return redirect()->to('/login');
        }
    }
    //login logi
    public function login()
    {
        if (isset($_SESSION['loggedIn'])) {
            return redirect()->to('/dashboard');
        } else {
            return view('login');
        }
    }
    public function logout()
    {
        session_destroy();
        return redirect()->to('/login');
    }
    //register logic
    public function register()
    {
        if (isset($_SESSION['loggedIn'])) {
            return redirect()->to('/dashboard');
        } else {
            return view('register');
        }
    }
    public function dashboard()
    {
        if (isset($_SESSION['loggedIn'])) {
            return view('dashboard',['title' => 'dashboard']);
        } else {
            return redirect()->to('/login');
        }
    }
    //login page
    public function doLogin()
    {
        $email = $this->request->getVar('email');
        $password = $this->request->getVar('password');
        if ($this->request->getMethod() == 'post') {
            $user = $this->userModel->verifyUser($email, $password);
            if (!empty($user->resultID->num_rows > 0) || $user->resultID->num_rows > 0) {
                $data = $user->getResult();
                if (!password_verify($password, $data[0]->password)) {
                    $this->session->set('danger', 'Incorrect password');
                    return redirect()->to('/login');
                } else {
                    $sessiondata = [
                        'name' => $data[0]->name,
                        'email' => $email,
                        'loggedIn' => true,
                    ];
                    $this->session->set($sessiondata);
                    return redirect()->to('/dashboard');
                }
            } else {
            }
        }
    }
    //register page
    public function doRegister()
    {
        if (strtolower($this->request->getMethod()) == 'post') {
            $data = ['name' => $this->request->getVar('uname'), 'email' => $this->request->getVar('email'), 'password' => $this->request->getVar('password')];
            $this->userModel->createUser($data);
            $this->session->set('success', 'Account registered successfully');
            return redirect()->to('/login');
        } else {
            $this->session->set('danger', 'Failed to register');
            return redirect()->to('/register');
        }
    }
}

Code Explained

All method’s targeted in route file.

  1. Include Session library to use session.
  2. If you are familiar with OOP then you might know about construct if not then read about Construct
  3. Index is default method, when you do not mention any method in front of controller in your route file then index will get called.
  4. Login method basically called to target the view page and in condition we are checking if use logged in or not so that he cannot jump to login page again.
  5. Logout method for unset the session and logout the user.
  6. Register method is used for the same purpose to call the view file.
  7. doLogin method for login logic.
  8. doRegister method for Register logic.

Edit Route File

If you don’t know about the routing take a look at documentation then it would be easy for you to build login and register in CodeIgniter. Otherwise let me explain you. Routing is basically represent the all routes of a website in any framework. We do keep our pages URL in routing file. It does have some security like for “post” route we can specify post and for get route we can specify get in front of URL.

See in the code below.

<?php

namespace Config;

// Create a new instance of our RouteCollection class.
$routes = Services::routes();

// Load the system's routing file first, so that the app and ENVIRONMENT
// can override as needed.
if (is_file(SYSTEMPATH . 'Config/Routes.php')) {
    require SYSTEMPATH . 'Config/Routes.php';
}

/*
 * --------------------------------------------------------------------
 * Router Setup
 * --------------------------------------------------------------------
 */
$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Home');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
// The Auto Routing (Legacy) is very dangerous. It is easy to create vulnerable apps
// where controller filters or CSRF protection are bypassed.
// If you don't want to define all routes, please use the Auto Routing (Improved).
// Set `$autoRoutesImproved` to true in `app/Config/Feature.php` and set the following to true.
// $routes->setAutoRoute(false);

/*
 * --------------------------------------------------------------------
 * Route Definitions
 * --------------------------------------------------------------------
 */

// We get a performance increase by specifying the default
// route since we don't have to scan directories.

$routes->get('/', 'AuthController::index');
$routes->get('/login', 'AuthController::login');
$routes->post('/login/auth', 'AuthController::doLogin');
$routes->get('/logout', 'AuthController::logout');
$routes->get('/register', 'AuthController::register');
$routes->get('/dashboard', 'AuthController::dashboard');
$routes->post('/register/auth', 'AuthController::doRegister');

/*
 * --------------------------------------------------------------------
 * Additional Routing
 * --------------------------------------------------------------------
 *
 * There will often be times that you need additional routing and you
 * need it to be able to override any defaults in this file. Environment
 * based routes is one such time. require() additional route files here
 * to make that happen.
 *
 * You will have access to the $routes object within that file without
 * needing to reload it.
 */
if (is_file(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) {
    require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php';
}

Now, you are ready to go and can use this code too. Don’t forget to understand the code before copy.

Conclusion

Our Authentication system is ready in CodeIgniter 4. Basically I do work with Laravel mostly because of a company’s project I moved to CodeIgniter. I learned it, I decided to share it with you.

If you can add something into this please do comment below. I’ll add your changes too.

2 thoughts on “Login and Register in CodeIgniter 4”

  1. Very good article for a new CI developer like me.

    Found one issue that password_verify function used in AuthController is not defined.

    //code
    if (!password_verify($password, $data[0]->password)) {

    Reply

Leave a Comment