CodeIgniter 4: The Basic

Hello Devs,
Hope you are all safe and healthy at home.
CodeIgniter4 landed last month and I finally got the chance to use it on a new project. If you have been working on any MVC, using CodeIgniter 4 should be smooth. CodeIgniter 4 has been re-developed from scratch. Consider it as a new framework. I assume you have knowledge about MVC frameworks and will cover some basic features and code snippets with you.

Installation

CI4 provides you two options to install the framework

  • Install via composer
composer create-project codeigniter4/appstarter ci4

In the above command you can replace the ci4 with the name of your choice and this will create basic filesystem for you.

  • Manual Install (I prefer this)

File Structure

File structure for CodeIgniter 4 is different from what it was for CodeIgniter 3, here is structure below (under project folder ci4):

Folder and their functions:

  • App: The folder is where you will write your code and setup configurations.
  • App/Config: for your application configurations
  • App/Controllers: for your controllers
  • App/Models: for your models
  • App/Views: for your views
  • System: Core files
  • Public: The root folder for you application. You will keep your assets(js/css/image files) here.
  • Vendor: The third party modules used
  • Writable: folder to write your cache/session files.
  • .env: an import file that saves your environment specific configurations.

IMPORTANT: If you have installed CodeIgniter manually you need to run the following command inside your project folder

composer update

Also open the file .env and update the environment variable to development at like 17 like this.

#--------------------------------------------------------------------
# ENVIRONMENT
#--------------------------------------------------------------------
CI_ENVIRONMENT = development

Accessing the project

You can access the setup with url http://localhost/ci4/public. The following welcome page should appear:

/***********************************************************
* MOVING FORWARD PLEASE ALSO READ COMMENT IN CODE SNIPPETS
***********************************************************/

If all went well, let us start with making our new controller file app/Controllers/User.php to manage & display users.

<?php namespace App\Controllers;

class User extends BaseController
{

    /**
     * function to load the form
     *
     * @return void
     * @author Harpreet
     */
    function add()
    {
        helper("form"); // load the form helper
        echo view("User/add"); // echo the view
    }
}

Now create a new file app/Views/user/add.php

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CI4|Add User</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

</head>

<body class="">
    <div class="container">
        <div class='row'>
            <div class='col-12'>
                <div class="card mt-5 shadow">
                    <div class="card-header bg-primary">
                        <h1 class='text-light m-0'>Add User</h1>
                    </div>
                    <div class="card-body">
                        <div class="alert alert-danger">
                            <!-- code to display validation errors see controller validations -->
                            <?php echo  \Config\Services::validation()->listErrors(); ?>
                        </div>
                        <?php echo form_open("user/save");?>
                        <div class="form-group">
                            <label for="name">Your Name</label>
                            <input type="name" class="form-control" id="name" name='name' aria-describedby="nameHelp">
                            <small id="nameHelp" class="form-text text-muted">Will be used as your display name</small>
                        </div>

                        <div class="form-group">
                            <label for="email">Email address</label>
                            <input type="email" class="form-control" id="email" name='email' aria-describedby="emailHelp">
                            <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
                        </div>
                        <div class="form-group">
                            <input type="submit" value="Add User" class="btn btn-primary float-right">
                        </div>
                        <?php echo form_close();?>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>

</html>

Update .env to the following configuration at line 24

app.baseURL = 'http://localhost/ci4/public/index.php/'

You can view the form at http://localhost/ci4/public/index.php/user/add

The basic view form is ready, now we have to submit this and handle the request. CodeIgniter 4 provides beautiful ways to handle the request and validate the data. Let us add a new function to handle the save request from the form. Create a function to validate and save details.

The initial code looks like this.

public function save()
    {
        /* setup the validation rules for the request data */
        $validationRules = [
            'name' => 'required|alpha_space|min_length[3]|max_length[20]',
            'email' => 'required|valid_email|min_length[6]|max_length[90]'
        ];

        /* check if data is not valid */
        if (! $this->validate($validationRules)){
            /* reload the view */
            helper("form");
            echo view("User/add");
        }
        else{
            /* all is got, get the values */
            $this->request->getPost('email');
            $this->request->getPost('name');

            
        }
    }

Before me move forward we need to create database and a table with following code.

CREATE DATABASE `ci4`;
USE ci4;
CREATE TABLE `users` (
  `user_id` int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `user_display_name` varchar(20) NOT NULL,
  `user_email` varchar(80) NOT NULL,
  `added_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `deleted_on` datetime NULL
);

Next we need to update our database details to config file. Now it is important to know that you can do this in 2 ways.

  1. Using the file app/Config/Database.php
  2. Using file .env

The purpose of .env file is to keep your configurations hidden from the code files. It is recommended to do same. The database configurations will be automatically picked. Here are the updates done to the .env file around line 49.

#--------------------------------------------------------------------
# DATABASE
#--------------------------------------------------------------------

database.default.hostname = localhost
database.default.database = ci4
database.default.username = root
database.default.password = root
database.default.DBDriver = MySQLi

Now create a new model file app/Models/Usermodel.php with basic setup.

<?php namespace App\Models;

use CodeIgniter\Model;

class Usermodel extends Model
{
    /* name of related table */
    protected $table = 'users';

    /* the primary key for the table */
    protected $primaryKey = 'user_id';

    /* how do you want the results to retrun */
    protected $returnType = 'object'; /* 'array' OR 'object' */

    /* if you want to flag the record as deleted 
    BUT NOT actually delete it. This requires a database field with delete timestamp */
    protected $useSoftDeletes = TRUE;

    /* array list of fields you would like to allow working with */
    protected $allowedFields = ['user_display_name', 'user_email'];

    /* to use timestamps */
    protected $useTimestamps = TRUE;

    protected $createdField  = 'added_on';

    /* we are not using it yet. */
    // protected $deletedField  = 'deleted_at';


    /* There are ways force database validation here 
    see https://codeigniter.com/user_guide/models/model.html#validating-data
    */
    protected $validationRules    = [];
    protected $validationMessages = [];
    protected $skipValidation     = false;

}

If you see there are no functions defined in the model. Well, CodeIgniter models provide some basic functions to read and write data you check those functions at here.

Now jump back to our controller to save the data. Add the use statement at line 2 in your controller like so:

<?php namespace App\Controllers;

use app\Models\Usermodel; // use the model we created

class User extends BaseController
{

Update the save() function and update it to be able to use our new model. (READ THE COMMENTS IN CODE)

public function save()
    {
        /* setup the validation rules for the request data */
        $validationRules = [
            'name' => 'required|alpha_space|min_length[3]|max_length[20]',
            'email' => 'required|valid_email|min_length[6]|max_length[90]'
        ];

        /* check if data is not valid */
        if (! $this->validate($validationRules)){
            /* reload the view */
            $this->add();
        }
        else{
            /* all is got, get the values */
            $email = $this->request->getPost('email');
            $name = $this->request->getPost('name');

            /* get model instance */
            $userModel = new Usermodel();

            /* using try catch to handle any errors */

            try {

                /* 
                    function SAVE() is the magic function provided by core model from CodeIgniter4,
                    simply pass the data and you are ready
                */
                $userModel->save([
                    'user_display_name' => $name,
                    'user_email'  => $email
                ]);

                /* when saved redirect to list page */
                redirect()->to("user/list");
            } 
            catch (\Exception $e) {
                /* a way to show error, you can customise this */
                throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
            }
            
        }
    }

Now create a function to list the users that have been added to database.

/**
     * function to list users
     *
     * @return void
     * @author Harpreet 
     */
    function list()
    {
        $userModel = new Usermodel();

        /* getting all records from database
        call this function magical, we did not define it, yet we can use it.
         */
        try {
            $users = $userModel->findAll();
            echo view("User/list", ['users' => $users]);
        }
        catch (\Exception $e)
        {
            /* a way to show error, you can customise this */
            throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
        }
    }

The view file to show the list of users:

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CI4|Add User</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

</head>

<body class="">
    <div class="container">
        <div class='row'>
            <div class='col-12'>
                <div class="card mt-5 shadow">
                    <div class="card-header bg-primary">
                        <h1 class='text-light m-0'>Current Users</h1>
                    </div>
                    <div class="card-body">
                        <table class="table table-bordered table-striped">
                            <thead>
                                <th>Id</th>
                                <th>Name</th>
                                <th>Email</th>
                                <th>Added On</th>
                            </thead>
                            <tbody>
                                <?php foreach ($users as $user):?>
                                    <tr>
                                        <td>
                                            <?php echo $user->user_id;?>
                                        </td>
                                        <td>
                                            <?php echo $user->user_display_name;?>
                                        </td>
                                        <td>
                                            <?php echo $user->user_email;?>
                                        </td>
                                        <td>
                                            <?php echo $user->added_on;?>
                                        </td>
                                    </tr>
                                <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>

</html>

This is how the basic setup works with CodeIgniter 4. I recommend that you must read the official documentation for more details. I will cover some more steps in coming weeks.

You can download this code on github as well.

Cover Photo by Safar Safarov on Unsplash

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.