CodeIgniter 4 AJAX Tutorial
About Lesson

To create a basic CRUD (Create, Read, Update, Delete) application with CodeIgniter 4, follow these steps:

 

Step 1: Database Setup

CREATE TABLE `customer_info` (
`id` bigint(20) NOT NULL,
`name` varchar(100) NOT NULL,
`email` varchar(255) NOT NULL,
`address` varchar(255) NOT NULL,
`mobile_number` varchar(100) DEFAULT NULL,
`ip_address` varchar(255) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`status` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
ALTER TABLE `customer_info`
  ADD PRIMARY KEY (`id`);

 

Step 2: Controller

Create a controller to handle CRUD operations. Create a new file named Customer.php in the app/Controllers/customer folder.

<?php
namespace App\Controllers\customer;

use App\Controllers\BaseController;

use App\Models\customer\CustomerModel;
use App\Models\customer\CustomerDeferModel;

class Customer extends BaseController {

public function __construct() {
$db = db_connect();
$this->session = \Config\Services::session();

$this->customer = new CustomerModel($db);
$this->customerDefer = new CustomerDeferModel($db);

$this->ip_address = $_SERVER['REMOTE_ADDR'];
$this->datetime = date("Y-m-d H:i:s");

}

public function index() {
$this->list();
}

public function list() {
$data = [];
$data ['content_title'] = 'List of Customers';
$data ['main_content'] = 'customer/list';
echo view('innerpages/template', $data);
}

public function edit() {
$id = $this->request->getPost('id');
$result = $this->customer->getEntry(['id' => $id]);
$html = '';
if($result) {
$html = '
<form id="form-update-customer" method="post" autocomplete="off">
<input type="hidden" name="id" value="'.$result->id.'"/>
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Update Customer</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="modal-message">
</div>
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Name" value="'.$result->name.'" required>
</div>
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" id="email" name="email" placeholder="Email" value="'.$result->email.'" required>
</div>
<div class="form-group">
<label>Mobile No.</label>
<input type="text" class="form-control" id="mobile_number" name="mobile_number" value="'.$result->mobile_number.'" placeholder="Mobile No." maxlength="10" required>
</div>
<div class="form-group">
<label>Address</label>
<input type="text" class="form-control" id="address" name="address" placeholder="Address" value="'.$result->address.'" required>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Update Customer</button>
</div>
</form>
';
}
echo $html;
}

public function create() {
$name = $this->request->getPost('name');
$email = $this->request->getPost('email');
$address = $this->request->getPost('address');
$mobile_number = $this->request->getPost('mobile_number');

$where = [
'email' => $email,
];
$has_account = $this->customer->getEntry($where);
if($has_account) {
$json = [
'status' => false,
'message' => showDangerMessage("Entered email address is already exists."),
];
} else {
$data = [
'name' => $name,
'email' => $email,
'address' => $address,
'mobile_number' => $mobile_number,
'ip_address' => $this->ip_address,
'created_at' => $this->datetime,
'status' => "1",
];
$result = $this->customer->addEntry($data);
if($result) {
$json = [
'status' => true,
'message' => showSuccessMessage("New record has been created successfully"),
];
} else {
$json = [
'status' => false,
'message' => showDangerMessage("Something went wrong. Please try again!"),
];
}
}
echo json_encode($json);
}

public function update() {
$id = $this->request->getPost('id');
$name = $this->request->getPost('name');
$email = $this->request->getPost('email');
$address = $this->request->getPost('address');
$mobile_number = $this->request->getPost('mobile_number');

$where = [
'id !=' => $id,
'email' => $email,
];
$has_account = $this->customer->getEntry($where);
if($has_account) {
$json = [
'status' => false,
'message' => showDangerMessage("Entered email address is already exists."),
];
} else {
$data = [
'name' => $name,
'email' => $email,
'address' => $address,
'mobile_number' => $mobile_number,
'ip_address' => $this->ip_address,
];
$result = $this->customer->updateEntry(['id' => $id], $data);
if($result) {
$json = [
'status' => true,
'message' => showSuccessMessage("Selected record has been updated successfully"),
];
} else {
$json = [
'status' => false,
'message' => showDangerMessage("Something went wrong. Please try again!"),
];
}
}
echo json_encode($json);
}

public function delete() {
$id = $this->request->getPost('id');
$result = $this->customer->deleteEntry(["id" => $id]);
if($result) {
$json = [
'message' => showSuccessMessage("The selected record has been deleted successfully."),
'status' => true,
];
} else {
$json = [
'message' => showDangerMessage("Something went wrong. Please try again."),
'status' => false,
];
}
echo json_encode($json);
}

public function datatable() {
$postData = $this->request->getPost();
$i = $this->request->getPost('start');
$result = $this->customerDefer->getRows($postData);
$arrayList = $this->getRows($i, $result);
$output = array(
"draw" => $this->request->getPost('draw'),
"recordsTotal" => $this->customerDefer->countAll($this->request->getPost()),
"recordsFiltered" => $this->customerDefer->countFiltered($this->request->getPost()),
"data" => $arrayList,
);
echo json_encode($output);
}

function getRows($i, $result) {
$arrayList = [];
foreach($result as $row) {
$action = ' <button type="button" name="btn-edit" class="btn btn-sm btn-primary" data-id="'.$row->id.'" title="Edit">Edit</button>';
$action .= ' <button type="button" name="btn-delete" class="btn btn-sm btn-danger" data-id="'.$row->id.'" title="Delete">Delete</button>';
$arrayList [] = [
++$i,
$row->name,
$row->email,
$row->mobile_number,
$row->address,
$action,
];
}
return $arrayList;
}
}

 

Step 3: Model

Create a model to handle database operations. Create a new file named CustomerModel.php and CustomerDeferModel.php in the app/Models/customer folder.

CustomerModel.php

<?php
namespace App\Models\customer;

use CodeIgniter\Model;
use CodeIgniter\Database\ConnectionInterface;

class CustomerModel extends Model {

protected $db;
public function __construct(ConnectionInterface &$db) {
$this->db =& $db;

$this->table = 'customer_info';
}

public function addEntry($data) {
$this->db
->table($this->table)
->insert($data);
return $this->db->insertID();
}

public function updateEntry($where, $data) {
return $this->db
->table($this->table)
->where($where)
->set($data)
->update();
}

public function deleteEntry($where) {
return $this->db
->table($this->table)
->where($where)
->delete();
}

public function getEntry($where) {
return $this->db
->table($this->table)
->where($where)
->get()
->getRow();

}

public function getEntryList($where = 0) {
if($where) {
return $this->db
->table($this->table)
->where($where)
->get()
->getResult();
} else {
return $this->db
->table($this->table)
->get()
->getResult();
}
}

public function getNumRows($where) {
return $this->db
->table($this->table)
->where($where)
->get()
->getNumRows();

}
}

 

CustomerDeferModel.php

<?php namespace App\Models\customer;

use CodeIgniter\Model;
use CodeIgniter\Database\ConnectionInterface;

class CustomerDeferModel extends Model {

protected $db;
protected $table;
protected $column_order;
protected $column_search;
protected $builder;
public function __construct(ConnectionInterface &$db) {
$this->db =& $db;
$this->table = 'customer_info';
$field_names = $this->db->getFieldNames($this->table);
$this->column_order = $this->getColumnOrder($field_names);
$this->column_search = $this->getColumnSearch($field_names);
}

public function getColumnOrder($field_names) {
$column_order = [];
$column_order[0] = null;
foreach($field_names as $row) {
$column_order [] = $row;
}
return $column_order;
}

public function getColumnSearch($field_names) {
$column_order = [];
foreach($field_names as $row) {
$column_order [] = $row;
}
return $column_order;
}

public function getRows($postData) {
$this->_get_datatables_query($postData);
if($postData['length'] != -1){
$this->builder->limit($postData['length'], $postData['start']);
}
$query = $this->builder->get();
return $query->getResult();
}

public function countAll($postData) {
$this->builder = $this->db->table($this->table);
return $this->builder->countAllResults();
}

public function countFiltered($postData) {
$this->_get_datatables_query($postData);
$query = $this->builder->get();
return $this->builder->countAll();
}

private function _get_datatables_query($postData) {

$this->builder = $this->db->table($this->table)
->orderBy('id', 'DESC');
$i = 0;
// loop searchable columns
foreach($this->column_search as $item){
// if datatable send POST for search
if($postData['search']['value']){
// first loop
if($i===0){
// open bracket
$this->builder->groupStart();
$this->builder->like($item, $postData['search']['value']);
} else{
$this->builder->orLike($item, $postData['search']['value']);
}

// last loop
if(count($this->column_search) - 1 == $i){
// close bracket
$this->builder->groupEnd();
}
}
$i++;
}

if(isset($postData['order'])){
$this->builder->orderBy($this->column_order[$postData['order']['0']['column']], $postData['order']['0']['dir']);
}else if(isset($this->order)){
$order = $this->order;
$this->builder->orderBy(key($order), $order[key($order)]);
}
}
}

 

Step 4: Create Views

Create views (header.php, footer.php, and template.php) in the app/Views/innerpages folder to separate the header and footer.

header.php

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

<head>
<title><?php echo $content_title; ?></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.7/css/jquery.dataTables.min.css"/>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js"></script>
</head>

<body>

 

footer.php


</body>

</html>

 

template.php

<?php

echo view("innerpages/header");
echo view($main_content);
echo view("innerpages/footer");

 

Create views (list.php) in the app/Views/customer folder for listing, creating, updating, and deleting records.

list.php

<div class="jumbotron text-center">
<h1>Welcome to Infovistar.in</h1>
<p>CRUD Example with AJAX</p>
</div>
<div class="container">
<div class="row">
<div class="col-sm-12 message">
</div>
<div class="col-sm-12">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#modal-add-customer">Add Customer</button>
</div>
<div class="col-sm-12 mt-1">
<div class="table-responsive">
<table id="table-customer" class="table table-sm table-bordered table-striped table-hover" width="100%">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
<th>Mobile</th>
<th>Address</th>
<th>Action</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div>

<div class="modal fade" id="modal-add-customer" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form id="form-add-customer" method="post" autocomplete="off">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Add Customer</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="modal-message">
</div>
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Name" required>
</div>
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" id="email" name="email" placeholder="Email" required>
</div>
<div class="form-group">
<label>Mobile No.</label>
<input type="text" class="form-control" id="mobile_number" name="mobile_number" placeholder="Mobile No." maxlength="10" required>
</div>
<div class="form-group">
<label>Address</label>
<input type="text" class="form-control" id="address" name="address" placeholder="Address" required>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Add Customer</button>
</div>
</form>
</div>
</div>
</div>

<div class="modal fade" id="modal-update-customer" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="edit-customer"></div>
</div>
</div>
</div>

<script>
$(document).ready(function() {
var table_customer = $("#table-customer").DataTable({
"processing":true,
"serverSide":true,
"order":[],
"ajax": {
url : '<?php echo base_url("customer/datatable") ?>',
type:"POST"
},
"columnDefs":[
{
"targets":[0],
"orderable":false,
},
],
});

$('#table-customer tbody').on( 'click', 'button', function () {
let id = $(this).attr('data-id');
if(this.name == "btn-delete") {
var isDelete = confirm("Are you sure you want to delete this?");
if(isDelete) {
$.post("<?php echo base_url("customer/delete"); ?>", {id: id}, function( result ) {
$(".message").html(result.message);
if(result.status) {
table_customer.ajax.reload();
}
}, 'json');
}
} if(this.name == "btn-edit") {
$.post("<?php echo base_url("customer/edit"); ?>", {id: id}, function( result ) {
$(".edit-customer").html(result);
$("#modal-update-customer").modal("show");
});
}
});

$("body").on("submit", "#form-add-customer", function(e) {
e.preventDefault();
let data = $(this).serialize();
$.post('<?php echo base_url("customer/create"); ?>', data, function(result) {
if(result.status) {
$(".message").html(result.message);
table_customer.ajax.reload();
$("#form-add-customer")[0].reset();
$("#modal-add-customer").modal("hide");
} else {
$(".modal-message").html(result.message);
}
}, 'json');
});

$("body").on("submit", "#form-update-customer", function(e) {
e.preventDefault();
let data = $(this).serialize();
$.post('<?php echo base_url("customer/update"); ?>', data, function(result) {
if(result.status) {
$(".message").html(result.message);
table_customer.ajax.reload();
$("#form-update-customer")[0].reset();
$("#modal-update-customer").modal("hide");
} else {
$(".modal-message").html(result.message);
}
}, 'json');
});
});
</script>

 

Step 5: Set Up Routes

Edit the app/config/Routes.php file to define routes for your controller.

// Customer Routes
$routes->group('customer', function($routes) {
$routes->get('/', 'customer\Customer::index');
$routes->get('list', 'customer\Customer::list');
$routes->post('datatable', 'customer\Customer::datatable');
$routes->post('create', 'customer\Customer::create');
$routes->post('edit', 'customer\Customer::edit');
$routes->post('update', 'customer\Customer::update');
$routes->post('delete', 'customer\Customer::delete');
});

 

Step 6: BaseController

<?php

namespace App\Controllers;

use CodeIgniter\Controller;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;

/**
* Class BaseController
*
* BaseController provides a convenient place for loading components
* and performing functions that are needed by all your controllers.
* Extend this class in any new controllers:
* class Home extends BaseController
*
* For security be sure to declare any new methods as protected or private.
*/
abstract class BaseController extends Controller
{
/**
* Instance of the main Request object.
*
* @var CLIRequest|IncomingRequest
*/
protected $request;

/**
* An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* @var array
*/
protected $helpers = [
'url', 'form', 'array', 'date',
'message_helper'
];

/**
* Be sure to declare properties for any property fetch you initialized.
* The creation of dynamic property is deprecated in PHP 8.2.
*/
// protected $session;

/**
* @return void
*/
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);

// Preload any models, libraries, etc, here.

// E.g.: $this->session = \Config\Services::session();
}
}

 

Step 7: Custom Helpers

Create a helper (message_helper.php) in the app/Helpers folder.

<?php

function showSuccessMessage($message) {
return '<div class="alert alert-success">
<strong>Great!</strong> '.$message.'
</div>';
}

function showDangerMessage($message) {
return '<div class="alert alert-danger">
<strong>Oops!</strong> '.$message.'
</div>';
}

 

Infovistar CRUD Operation