Simple CRUD App in CodeIgniter 4

Sanjay Bandla
9 min readJan 31, 2022

In this tutorial, we will be creating a CRUD (Create, Read, Update, Delete) app in CodeIgniter 4 with MySQL and Bootstrap.

CRUD Introduction

CRUD is an acronym that refers to the four functions that are considered necessary to implement a persistent storage application: Create, Read, Update and delete.

Installation & Environment Setup

You can install the CodeIgniter latest version via one of the following ways.

composer create-project codeigniter4/appstarter ci4
git clone <https://github.com/codeigniter4/framework.git>

Note: If you are installing it through composer, make sure you have uncommented;extension=intl in your php.ini file.

After installation, we need to install the dependency packages by running composer install in your project directory, then open the .env file and update the credentials accordingly to access your MySQL database.

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

Implementing the CRUD Operations

Creating Model & Migration

As CodeIgniter is based on the Model-View-Controller (MVC) pattern, it separates application logic from the presentation in the following 3 interconnected parts.

  1. The Model handles the data passed between the database and the user interface.
  2. The View is information that is being presented to a user.
  3. The Controller serves as an intermediary among the Model, the View, and any other resources needed to process the HTTP request and generate a web page.

Here, we only need a single model for our app. So, let’s create the User model with a migration file by running the following commands in the terminal.

php spark make:model User
php spark make:migration users

The above command will generate a model file app\Models\User.php and a migration file app\Database\Migrations\[timestamp]_Users.php.

app\Models\User.php

<?phpnamespace 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', 'age'];
// Dates
protected $useTimestamps = false;
protected $dateFormat = 'datetime';
protected $createdField = 'created_at';
protected $updatedField = 'updated_at';
protected $deletedField = 'deleted_at';
// Validation
protected $validationRules = [];
protected $validationMessages = [];
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 = [];
}

app\Database\Migrations\[timestamp]_Users.php

<?phpnamespace App\\Database\\Migrations;use CodeIgniter\\Database\\Migration;class Users extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 5,
'auto_increment' => true,
],
'name' => [
'type' => 'VARCHAR',
'constraint' => '100',
],
'age' => [
'type' => 'VARCHAR',
'constraint' => '3',
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('users');
}
public function down()
{
$this->forge->dropTable('users');
}
}

In the above migration file, we have added 3 columns as id, name, age where name and age are allowed fields in our model app\Models\User.php to perform CRUD operations. And id is the primary key in our table to refer the user. Now to migrate the above table in our database, just run the following command in the terminal which will generate a users table.

php spark migrate

Creating the Controller and Routes

After creating the model and migration, let’s create a restful controller that initializes typical functions for CRUD operations with RESTful Resource Handling. We can create a controller from the terminal by following the below command.

php spark make:controller Users --restful

The above command will generate a controller with the name Users that has the following code by default.

app\Controllers\Users.php

<?phpnamespace App\\Controllers;use CodeIgniter\\RESTful\\ResourceController;class Users extends ResourceController
{
/**
* Return an array of resource objects, themselves in array format
*
* @return mixed
*/
public function index()
{
//
}
/**
* Return the properties of a resource object
*
* @return mixed
*/
public function show($id = null)
{
//
}
/**
* Return a new resource object, w/9,.ith default properties
*
* @return mixed
*/
public function new()
{
//
}
/**
* Create a new resource object, from "posted" parameters
*
* @return mixed
*/
public function create()
{
//
}
/**
* Return the editable properties of a resource object
*
* @return mixed
*/
public function edit($id = null)
{
//
}
/**
* Add or update a model resource, from "posted" properties
*
* @return mixed
*/
public function update($id = null)
{
//
}
/**
* Delete the designated resource object from the model
*
* @return mixed
*/
public function delete($id = null)
{
//
}
}

Note: Representational State Transfer (REST) is an architectural style for distributed applications. REST defines a set of constraints for how the architecture of an Internet-scale distributed hypermedia system (such as the Web) should behave.

Users class in the controller extends ResourceController from CodeIgniter and defines a bunch of functions that will be used to perform CRUD operations against our User Model.

To access the methods of the controller, we need to set the routes for our app under app\Config\Routes.php. You can quickly create a handful of RESTful routes for a single resource with the resource() method. This creates the most common routes needed for full CRUD of a resource: create a new resource, update an existing one, list all of that resource, show a single resource, and delete a single resource.

$routes->get('/', function() {    return redirect()->to('users');
});
$routes->resource('users'); // RESTful resource

The above resource method indicates that whenever the app gets a request having users in the call, it will be handled by the methods of the users controller. Using the resource method, we can have the following routes mapping to the respected controller methods as given below.

  • GET /users is mapped to index()
  • GET /users/new is mapped to new()
  • POST /users is mapped to create()
  • GET /users/(:segment) is mapped to show()
  • GET /users/(:segment)/edit is mapped to edit()
  • PUT/PATCH /users/(:segment) is mapped to update()
  • DELETE /users/(:segment) is mapped to delete()

C: Implementing the Create Operation and Adding a Form

In order to perform create operation, we need to have a form that takes name and age as inputs and returns to the create() method in our controller app\Controllers\Users.php.

Step 1: Create template views

Here, we create a home view where we include Bootstrap and JQuery to be used on every page of our application where it’s required. So, create home, header views in the app and add the following code.

app\Views\home.php

<!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>CodeIgniter 4 Crud App</title>
https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body class="my-5">
<div class="container">

<?php
if(session()->getFlashdata('status') != '') { echo '<div class="alert alert-info">'.session()->getFlashdata('status').'</div>';
}
?>
<?= $this->renderSection('content') ?>
</div> https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous">
https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous">
</body>
</html>

app\\Views\\Templates\\header.php

<h3>CodeIgniter 4 - Simple CRUD App</h3><div class="text-end my-2">
<a href="/users/new" class="btn btn-success">
Create New
</a>
</div>

Step 2: Add the following code in app\Views\new_user.php for the user form that takes name and age as inputs

<?= $this->extend('home') ?>
<?= $this->section('content') ?>
<form action="/users" method="post"> <h3>Create New User</h3><br> <div class="mb-3 row col-6">
<?php csrf_field() ?>
<label class="form-label">Name</label>
<input type="text" class="form-control" name="name" required>
</div>
<div class="mb-3 row col-6">
<label class="form-label">Age</label>
<input type="number" class="form-control"name="age" required>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form><?= $this->endSection() ?>

Step 3: Create functions in the app\Controllers\Users.php controller

Go to the Users controller and add the below code to it.

app\Controllers\Users.php

private $db;

public function __construct()
{
$this->db = db_connect();
}
public function new()
{
return view('new_user');
}
public function create()
{
$data = [
'name' => $this->request->getPost('name'),
'age' => $this->request->getPost('age')
];

$result = $this->db->table('users')->insert($data);

$status = ($result) ? 'Record has been inserted :)': 'Record has not been inserted :(';

return redirect()->to(base_url('users'))->with('status', $status);
}

Now, whenever we visit /users/new, a form will be displayed on the screen as shown in the below picture.

Create new user form

And when we submit the data through the form, create() in the controller will be called where we get the data and insert it into the users table. On performing the query, we redirect the user to /users page with the $status variable that indicates the result of the query.

R: Implementing the Read Operation

As of now, we are able to insert the data into the table with the help of HTML form. Let’s retrieve and display the inserted data from our MySQL table.

Step 1: Re-open to app\Controllers\Users.php, update the index() as follows

public function index()
{
$users = $this->db->table('users')->get()->getResult();

$data['users'] = $users;

return view('read_users',$data);
}

It will fetch the results from the MySQL database and return to the read_users view with users data.

Step 2: Create app\Views\read_users.php and add the bootstrap table in it

<?= $this->extend('home') ?>
<?= $this->section('content') ?>
<?= $this->include('Templates/header') ?>
<table class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Age</th>
<th scope="col">Edit</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
<?php foreach($users as $user) : ?> <tr>
<td><?= $user->id ?></td>
<td><?= $user->name ?></td>
<td><?= $user->age ?></td>
<td>
<a href="<?= base_url('/users/'.$user->id.'/edit') ?>" class="btn btn-primary">Edit</a>
</td>
<td>
<a class="btn btn-danger" onclick='if(confirm(`Do you want delete this record`)) { document.forms[`form_<?= $user->id ?>`].submit() }'>Delete</a>
</td>
</tr>
<!-- DELETE Form -->
<form action='/users/<?= $user->id ?>' method='post' name='form_<?= $user->id ?>' class="d-none">
<?= csrf_field() ?>
<input type='hidden' name='_method' value='DELETE' />
</form>

<?php endforeach ?>
</tbody>
</table>
<?= $this->endSection() ?>

By getting users’ data from index(), we can display them in the above view with PHP foreach() loop.

If everything goes well, you will see the results in the bootstrap table by visiting /users in your browser like below.

U: Implementing the Update Operation

The next thing we need to do is create an update form and implement edit(), update() in the controller.

Step 1: Add the below code in app\Views\update_form.php to create an update form

<?= $this->extend('home') ?>
<?= $this->section('content') ?>
<form action="/users/<?= $user->id; ?>" method="post"> <h3>Update User Data for Id No: <?= $user->id; ?></h3><br> <div class="mb-3 row col-6">
<?php csrf_field() ?>
<input type="hidden" name="_method" value="PUT" />
<input type="hidden" name="id" value="<?php echo $user->id; ?>">
<label class="form-label" required>Name</label>
<input type="text" class="form-control" name="name" value="<?= $user->name ?>" required>
</div>
<div class="mb-3 row col-6">
<label class="form-label">Age</label>
<input type="number" class="form-control"name="age" value="<?= $user->age ?>">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form><?= $this->endSection() ?>

The above update form is displayed at /users/(:segment)/edit respected to the chosen user from users table which is located at /users page.

Step 2: Update edit() and update() in the controller

app\Controllers\Users.php

First of all, we have to import the User model into our controller before the class declaration in order to use it under update()

use App\Models\User;public function edit($id = null)
{
$user = $this->db->table('users')->getWhere(['id'=>$id],1)->getRow();
$data['user'] = $user;

return view('update_form',$data);

}
public function update($id = null)
{
$user = new User();

$data = [
'name' => $this->request->getPost('name'),
'age' => $this->request->getPost('age'),
];
$result = $user->update($id, $data);
$status = ($result) ? 'Records has been updated :)': 'Records has not been updated :(';

return redirect()->to(base_url('users'))->with('status', $status);
}
  • edit(): As shown in the above code, edit() in the app\\Controllers\\Users.php fetches the respected user from the $id parameter and passes it to the update_form view.
  • update(): It is responsible for updating the given data from the update_form into the users table. Here, we are importing the User Model into the controller and assigning it to the $user variable. With the help of $id parameter, we are able to update the concerned user with $data variable. Right after executing the query, we are redirecting the user to /users with result status.

D: Implementing the Delete Operation

This is the final stage in our CRUD app where we have to delete the user. To perform such an operation, we have delete() in our controller. So, let’s update this method accordingly.

app\Controllers\Users.php

public function delete($id = null)
{
$result = $this->db->table('users')->where('id', $id)->delete();

$status = ($this->db->affectedRows()) ? 'Records has been deleted :)': 'Records has not been deleted :(';

return redirect()->to(base_url('users'))->with('status', $status);
}

This method can be called by DELETE /users/(:segment). However, we have already added the below required code in our app\\Views\\read_users.php

<!-- DELETE Form -->
<form action='/users/<?= $user->id ?>' method='post' name='form_<?= $user->id ?>' class="d-none">
<?= csrf_field() ?>
<input type='hidden' name='_method' value='DELETE' />
</form>

So, we can simply achieve this operation by clicking the delete button in our bootstrap table located at /users page.

Conclusion

That’s it. We’ve just created an entire CRUD application in CodeIgniter 4 with MySQL and Bootstrap.

Hope you found this tutorial useful and I’ll see you in the next one.

Source: https://github.com/Sanjay-Sahu-Bandla/CodeIgniter4-Simple-CRUD

--

--