Launch offer
Business website $150 USD Custom plugin $200 USD Ready in 5 days
Get a quote
CodeIgniter

CodeIgniter Complete Tutorial: Beginner to Advanced (74 Topics with Code)

Complete CodeIgniter 4 tutorial covering MVC, routing, validation, MySQL, migrations, REST APIs, JWT, security, and a final CRUD + authentication project — with practical code examples.

CodeIgniter Complete Tutorial: Beginner to Advanced (74 Topics with Code) — a practical guide to CodeIgniter complete tutorial with clear examples you can reuse in real projects.

This complete CodeIgniter 4 tutorial covers 74 topics — from installation and MVC basics to validation, MySQL, migrations, REST APIs, JWT, security, and a final CRUD + authentication project. Written in beginner-friendly language with practical code.

Course roadmap

1. Introduction to CodeIgniter

CodeIgniter is a fast, lightweight PHP framework that follows MVC. This series focuses on CodeIgniter 4 with practical examples for controllers, views, models, validation, databases, APIs, and full projects.

  1. Learn CI4 project structure and routing first.
  2. Practice controllers, views, and forms.
  3. Add database, models, then APIs and auth.

What you will build toward

MVC basics → forms/validation → MySQL CRUD
Migrations/seeders → REST APIs → JWT auth
Final project: CRUD + Authentication + REST API

2. What is CodeIgniter?

CodeIgniter helps you build web apps quickly with routing, controllers, views, libraries, and helpers — without forcing a heavy architecture.

MVC at a glance

Model      → database / business data
View       → HTML / templates
Controller → request handling / flow

3. CodeIgniter Features

CI4 includes a powerful router, HTTP layer, Query Builder, validation, migrations, filters (middleware), and excellent documentation — while staying approachable for beginners.

Feature checklist

- Lightweight & fast
- MVC pattern
- Query Builder & Models
- Form validation
- Filters (middleware)
- Migrations & seeders
- CSRF / XSS helpers
- REST-friendly controllers

4. CodeIgniter 4 vs CodeIgniter 3

CodeIgniter 4 is the modern version: namespaces, PHP 8+, improved HTTP layer, filters, and a cleaner structure. CI3 is legacy — new projects should use CI4.

Quick comparison

CI3: older structure, PHP 5.6+, fewer modern tools
CI4: namespaces, services, filters, spark CLI, PHP 8+
Recommendation: learn and build with CodeIgniter 4

5. CodeIgniter Installation

The recommended way to install CI4 is Composer. After install, point your web server to the `public/` folder.

  1. Install PHP, Composer, and MySQL/MariaDB.
  2. Create the project with Composer.
  3. Run `php spark serve` and open the local URL.

Install with Composer

composer create-project codeigniter4/appstarter ci-blog
cd ci-blog
php spark serve

6. CodeIgniter Server Requirements

CI4 needs a modern PHP version and common extensions (intl, json, mbstring, mysqlnd, etc.). Always confirm against the official docs for your exact version.

Check PHP

php -v
php -m | findstr /i "intl mbstring json"

7. Creating Your First CodeIgniter Project

After `composer create-project`, you get a working app. Customize `.env`, then start building routes and controllers.

First run

composer create-project codeigniter4/appstarter myapp
cd myapp
copy env .env
php spark key:generate
php spark serve

8. CodeIgniter Directory Structure

Most of your code lives in `app/` (Controllers, Models, Views, Config). `public/` is the web root. `writable/` stores logs, cache, and uploads.

Key folders

app/Controllers  Controllers
app/Models       Models
app/Views        Views
app/Config       Configuration
public/          Web root (index.php)
writable/        Logs, cache, uploads
vendor/          Composer packages

9. Configuration in CodeIgniter

CI4 uses PHP config classes in `app/Config`. Prefer reading secrets from `.env` instead of hardcoding them.

Read config values

$baseURL = config('App')->baseURL;
$db = config('Database')->default;

10. Environment Configuration in CodeIgniter

Copy `env` to `.env`, then set environment and database values. Never commit real secrets to git.

.env essentials

CI_ENVIRONMENT = development
app.baseURL = 'http://localhost:8080/'

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

11. Routing in CodeIgniter

Define routes in `app/Config/Routes.php`. You can use placeholders, groups, and named routes for clean URLs.

Basic routes

$routes->get('/', 'Home::index');
$routes->get('about', 'Pages::about');
$routes->get('posts/(:num)', 'Posts::show/$1');
$routes->post('contact', 'Contact::submit');

12. Controllers in CodeIgniter

Controllers sit between routes and models/views. Extend `BaseController` for shared helpers and services.

Controller skeleton

<?php
namespace AppControllers;

class Posts extends BaseController
{
    public function index()
    {
        return view('posts/index');
    }
}

13. Creating Your First Controller

Create a controller file under `app/Controllers`, add a method, then register a route that calls it.

  1. Create `Products` controller.
  2. Add `index()` method.
  3. Route `products` → `Products::index`.

Spark generate (optional)

php spark make:controller Products

Products controller

<?php
namespace AppControllers;

class Products extends BaseController
{
    public function index()
    {
        return 'Products list';
    }
}

14. Passing Data from Controller to View

Pass an associative array as the second argument to `view()`. Keys become variables inside the view.

Controller → view data

return view('welcome', [
    'title' => 'Home',
    'user'  => 'Imtiyaj',
]);

// welcome.php
// <h1><?= esc($title) ?></h1>

15. Views in CodeIgniter

Views live in `app/Views`. Keep them mostly presentational — put business logic in models/controllers.

Simple view

<!-- app/Views/home.php -->
<!DOCTYPE html>
<html>
<head><title><?= esc($title) ?></title></head>
<body>
  <h1>Welcome</h1>
</body>
</html>

16. Creating Layouts and Templates in CodeIgniter

CI4 supports view layouts so header/footer stay in one place while each page fills content sections.

Layout + page

<!-- Views/layout.php -->
<html><body>
  <?= $this->renderSection('content') ?>
</body></html>

<!-- Views/about.php -->
<?= $this->extend('layout') ?>
<?= $this->section('content') ?>
  <h1>About</h1>
<?= $this->endSection() ?>

17. View Data and Dynamic Content

Always escape output with `esc()` to reduce XSS risk. Use loops/conditions for dynamic lists.

Dynamic list

<?php foreach ($posts as $post): ?>
  <article>
    <h2><?= esc($post['title']) ?></h2>
  </article>
<?php endforeach; ?>

18. URL Helpers in CodeIgniter

Load the URL helper (often auto-loaded) to build portable links that respect your `baseURL`.

URL helpers

echo base_url('css/app.css');
echo site_url('posts/create');
echo current_url();
echo anchor('contact', 'Contact us');

19. Form Helpers in CodeIgniter

Form helpers generate HTML form tags and can include CSRF fields automatically when configured.

Form helper example

<?= form_open('login') ?>
  <?= form_input('email', set_value('email'), ['placeholder' => 'Email']) ?>
  <?= form_password('password') ?>
  <?= form_submit('submit', 'Login') ?>
<?= form_close() ?>

20. HTML Helpers in CodeIgniter

HTML helpers keep view code consistent for small reusable snippets like images and lists.

HTML helper samples

echo heading('Dashboard', 1);
echo img('images/logo.png', false, ['alt' => 'Logo']);
echo ul(['Home', 'About', 'Contact']);

21. Request and Response in CodeIgniter

CI4 exposes `$this->request` and `$this->response` in controllers for reading input and controlling output/status codes.

Request & response

$email = $this->request->getPost('email');
$json  = $this->request->getJSON(true);

return $this->response
    ->setStatusCode(201)
    ->setJSON(['ok' => true]);

22. GET and POST Methods in CodeIgniter

GET is for reading/filtering. POST is for submitting forms or creating resources. Validate both before trusting values.

Read GET/POST

$q = $this->request->getGet('q');
$name = $this->request->getPost('name');
$all = $this->request->getPost(); // array

23. Handling Form Data in CodeIgniter

Use `getPost()` / `getVar()` and keep a clear flow: receive → validate → save → redirect with flash message.

Handle contact form

public function submit()
{
    $data = [
        'name'    => $this->request->getPost('name'),
        'message' => $this->request->getPost('message'),
    ];
    // validate + save...
    return redirect()->to('/contact')->with('success', 'Sent');
}

24. Form Validation in CodeIgniter

Define rules, run validation, and redisplay the form with errors and old input on failure.

Validate in controller

$rules = [
    'email' => 'required|valid_email',
    'password' => 'required|min_length[8]',
];

if (! $this->validate($rules)) {
    return view('auth/login', [
        'validation' => $this->validator,
    ]);
}

25. Custom Validation Rules in CodeIgniter

Add reusable custom rules when you need project-specific validation (unique formats, domain checks, etc.).

Custom rule callback style

$rules = [
    'username' => [
        'rules'  => 'required|min_length[3]',
        'errors' => ['required' => 'Username is required'],
    ],
];
// Or register custom rules in ConfigValidation / rule classes.

26. Flash Messages in CodeIgniter

Flash messages appear once on the next request — perfect after form submit redirects.

Set and show flash

// Controller
return redirect()->to('/posts')->with('success', 'Post created');

// View
<?php if (session()->getFlashdata('success')): ?>
  <div class="alert"><?= esc(session()->getFlashdata('success')) ?></div>
<?php endif; ?>

27. Sessions in CodeIgniter

Use sessions for login state, cart data, and preferences. Configure the session driver in config/.env.

Session usage

session()->set('user_id', 15);
$id = session()->get('user_id');
session()->remove('user_id');
session()->destroy();

28. Cookies in CodeIgniter

Cookies are useful for remember preferences. Do not store sensitive secrets in normal cookies.

Cookie set/get

$this->response->setCookie('theme', 'dark', 86400);
$theme = $this->request->getCookie('theme');

29. Database Configuration in CodeIgniter

Set hostname, database name, username, password, and driver. Keep credentials in `.env`.

DB .env

database.default.hostname = localhost
database.default.database = ci_app
database.default.username = root
database.default.password =
database.default.DBDriver = MySQLi
database.default.DBPrefix =
database.default.port = 3306

30. Connecting MySQL Database in CodeIgniter

Once `.env` is set, use the database service or models. Test with a simple query during setup.

Test connection

$db = ConfigDatabase::connect();
$query = $db->query('SELECT 1 AS ok');
print_r($query->getRow());

31. Query Builder in CodeIgniter

Query Builder helps prevent SQL mistakes and supports chaining for select/where/join/order.

Query Builder select

$db = ConfigDatabase::connect();
$posts = $db->table('posts')
    ->select('id, title, created_at')
    ->where('is_published', 1)
    ->orderBy('id', 'DESC')
    ->get()
    ->getResultArray();

32. Select, Insert, Update and Delete in CodeIgniter

These four operations power most CRUD apps. Prefer Query Builder or Models for everyday work.

CRUD with Query Builder

$builder = $db->table('posts');

$builder->insert(['title' => 'Hello', 'body' => 'World']);
$builder->where('id', 1)->update(['title' => 'Updated']);
$row = $builder->where('id', 1)->get()->getRowArray();
$builder->where('id', 1)->delete();

33. Database Migrations in CodeIgniter

Migrations keep schema changes repeatable across machines and environments.

Create & run migration

php spark make:migration CreatePostsTable
php spark migrate
php spark migrate:rollback

Migration up()

$this->forge->addField([
    'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
    'title' => ['type' => 'VARCHAR', 'constraint' => 255],
    'created_at' => ['type' => 'DATETIME', 'null' => true],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('posts');

34. Database Seeders in CodeIgniter

Seeders insert starter records so you can develop UI/API features without manual SQL inserts.

Seeder example

// php spark make:seeder PostSeeder
$data = [
    ['title' => 'First post', 'body' => 'Hello'],
    ['title' => 'Second post', 'body' => 'CI4'],
];
$this->db->table('posts')->insertBatch($data);
// php spark db:seed PostSeeder

35. Models in CodeIgniter

CI4 models provide `find`, `save`, `insert`, `update`, and `delete` with protection via `$allowedFields`.

Basic model

<?php
namespace AppModels;
use CodeIgniterModel;

class PostModel extends Model
{
    protected $table = 'posts';
    protected $primaryKey = 'id';
    protected $allowedFields = ['title', 'body', 'user_id'];
    protected $useTimestamps = true;
}

36. Creating Custom Models in CodeIgniter

Keep complex queries inside model methods so controllers stay thin.

Custom finder

public function published()
{
    return $this->where('is_published', 1)
                ->orderBy('created_at', 'DESC')
                ->findAll();
}

37. Model Validation in CodeIgniter

Model-level `$validationRules` keep validation close to the data layer.

Model rules

protected $validationRules = [
    'title' => 'required|min_length[3]|max_length[255]',
    'body'  => 'required',
];

38. Relationships Between Tables in CodeIgniter

CI models do not force Eloquent-style relations, but you can implement belongs-to/has-many patterns with queries and joins.

Join example

return $this->select('posts.*, users.name AS author')
    ->join('users', 'users.id = posts.user_id')
    ->findAll();

39. Pagination in CodeIgniter

Pagination improves performance and UX for long lists like posts, products, or users.

Paginate posts

$model = new AppModelsPostModel();
$data['posts'] = $model->paginate(10);
$data['pager'] = $model->pager;
return view('posts/index', $data);

// View: <?= $pager->links() ?>

40. Searching and Filtering in CodeIgniter

Read `q` from the request and apply `like` / `where` conditions before pagination.

Search + paginate

$q = $this->request->getGet('q');
$model = new AppModelsPostModel();
if ($q) {
    $model->like('title', $q);
}
$data['posts'] = $model->paginate(10);
$data['pager'] = $model->pager;
$data['q'] = $q;

41. File Upload in CodeIgniter

Validate size/extension, then move the file to a safe directory outside or inside public as needed.

Upload handler

$file = $this->request->getFile('document');
if (! $file->isValid()) {
    return redirect()->back()->with('error', $file->getErrorString());
}
$name = $file->getRandomName();
$file->move(WRITEPATH . 'uploads', $name);

42. Image Upload and Validation in CodeIgniter

For images, validate type carefully and optionally resize with the Image library.

Image rules + move

$validation = ConfigServices::validation();
$validation->setRules([
    'avatar' => 'uploaded[avatar]|is_image[avatar]|max_size[avatar,2048]',
]);
if (! $validation->withRequest($this->request)->run()) {
    return redirect()->back()->withInput()->with('errors', $validation->getErrors());
}
$img = $this->request->getFile('avatar');
$img->move(FCPATH . 'uploads');

43. CRUD Application in CodeIgniter

CRUD is the core pattern for admin panels and content apps. Combine validation, flash messages, and redirects.

CRUD routes

$routes->get('posts', 'Posts::index');
$routes->get('posts/new', 'Posts::new');
$routes->post('posts', 'Posts::create');
$routes->get('posts/(:num)/edit', 'Posts::edit/$1');
$routes->post('posts/(:num)', 'Posts::update/$1');
$routes->post('posts/(:num)/delete', 'Posts::delete/$1');

44. AJAX with CodeIgniter

Detect AJAX calls, validate input, and respond with JSON status payloads for frontend fetch/XHR.

JSON AJAX endpoint

public function store()
{
    $text = $this->request->getPost('text');
    // save...
    return $this->response->setJSON([
        'success' => true,
        'message' => 'Saved',
    ]);
}

45. Creating REST APIs in CodeIgniter

REST APIs use HTTP verbs and JSON bodies/responses. Keep controllers focused on status codes and payloads.

API list endpoint

public function index()
{
    $posts = model('PostModel')->findAll();
    return $this->response->setJSON(['data' => $posts]);
}

46. API Authentication in CodeIgniter

Common options: API keys, session auth for first-party apps, or JWT for stateless APIs.

Simple API key filter idea

$key = $this->request->getHeaderLine('X-API-Key');
if ($key !== env('API_KEY')) {
    return $this->response->setStatusCode(401)->setJSON(['error' => 'Unauthorized']);
}

47. JWT Authentication in CodeIgniter

Issue a signed JWT on login and verify it in a filter on protected routes.

JWT flow (conceptual)

1. POST /login with email/password
2. Verify user + password_hash
3. Return JWT access token
4. Client sends Authorization: Bearer <token>
5. Filter verifies signature + expiry

48. CORS in CodeIgniter

Configure allowed origins/headers/methods carefully. Avoid `*` with credentials in production.

CORS headers example

return $this->response
    ->setHeader('Access-Control-Allow-Origin', 'http://localhost:5173')
    ->setHeader('Access-Control-Allow-Headers', 'Authorization, Content-Type')
    ->setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');

49. Email Sending in CodeIgniter

Configure from-address and mail protocol, then use the Email service to send messages.

Send email

$email = ConfigServices::email();
$email->setTo('user@example.com');
$email->setSubject('Welcome');
$email->setMessage('Thanks for joining!');
$email->send();

50. Sending Email with SMTP in CodeIgniter

SMTP is preferred over PHP mail() in real apps. Store host/user/pass in `.env`.

Email config (concept)

public string $protocol = 'smtp';
public string $SMTPHost = 'smtp.example.com';
public string $SMTPUser = 'apikey';
public string $SMTPPass = 'secret';
public int $SMTPPort = 587;
public string $SMTPCrypto = 'tls';

51. Authentication and Login System in CodeIgniter

Verify credentials, store user id in session, and guard routes with filters.

Login sketch

$user = model('UserModel')->where('email', $email)->first();
if (! $user || ! password_verify($password, $user['password'])) {
    return redirect()->back()->with('error', 'Invalid login');
}
session()->set('user_id', $user['id']);
return redirect()->to('/dashboard');

52. User Registration in CodeIgniter

Validate unique email, hash passwords, then insert the user and redirect to login.

Register user

$model = model('UserModel');
$model->insert([
    'name' => $this->request->getPost('name'),
    'email' => $this->request->getPost('email'),
    'password' => password_hash($this->request->getPost('password'), PASSWORD_DEFAULT),
]);

53. Password Hashing in CodeIgniter

Never store plain-text passwords. Use `PASSWORD_DEFAULT` and verify on login.

Hash + verify

$hash = password_hash('Secret123!', PASSWORD_DEFAULT);
$ok = password_verify('Secret123!', $hash); // true

54. Role-Based Access Control in CodeIgniter

Store a role on the user record and check it in filters before admin routes run.

Role check

if (session('role') !== 'admin') {
    return redirect()->to('/')->with('error', 'Forbidden');
}

55. Middleware / Filters in CodeIgniter

CI4 filters run before/after controllers. Register them in `app/Config/Filters.php`.

Auth filter sketch

public function before(RequestInterface $request, $arguments = null)
{
    if (! session()->get('user_id')) {
        return redirect()->to('/login');
    }
}

56. CSRF Protection in CodeIgniter

CI can auto-check CSRF tokens on POST/PUT/DELETE. Include the token in forms and AJAX headers.

CSRF field in form

<?= csrf_field() ?>
<!-- or -->
<input type="hidden" name="<?= csrf_token() ?>" value="<?= csrf_hash() ?>" />

57. XSS Protection in CodeIgniter

Escape everything you print in views with `esc()`. Do not trust raw HTML from users.

Escape output

<p><?= esc($userInput) ?></p>
<!-- Avoid unescaped user HTML unless sanitized intentionally -->

58. Error Handling in CodeIgniter

Use try/catch for expected failures and let CI’s exception handler manage unexpected errors. Keep `CI_ENVIRONMENT=production` on live servers.

Try/catch example

try {
    $db->transException(true)->transStart();
    // queries...
    $db->transComplete();
} catch (Throwable $e) {
    log_message('error', $e->getMessage());
    return redirect()->back()->with('error', 'Something went wrong');
}

59. Logging in CodeIgniter

Logs go under `writable/logs`. Use levels like error, warning, info, and debug.

Log messages

log_message('error', 'Payment failed for order {0}', [$orderId]);
log_message('info', 'User logged in');

60. Cache in CodeIgniter

Cache computed results with a TTL. Clear or refresh when underlying data changes.

Cache remember pattern

$cache = ConfigServices::cache();
$posts = $cache->get('posts_home');
if ($posts === null) {
    $posts = model('PostModel')->published();
    $cache->save('posts_home', $posts, 300); // 5 minutes
}

61. RESTful Controllers in CodeIgniter

Resource routes map HTTP verbs to controller actions consistently for APIs.

Resource routes

$routes->resource('api/posts', ['controller' => 'ApiPosts']);

62. API Response and Status Codes in CodeIgniter

Use 200/201 for success, 400 for validation errors, 401/403 for auth, 404 for missing, 500 for server errors.

JSON response helper style

return $this->response->setStatusCode(201)->setJSON([
    'status' => 'success',
    'data' => $post,
]);

63. Postman API Testing for CodeIgniter

Use Postman to send GET/POST/PUT/DELETE, set Bearer tokens, and inspect status codes/JSON bodies.

Postman checklist

1. Create environment (baseUrl)
2. Add requests for each endpoint
3. Set Authorization header for JWT
4. Assert status code + JSON keys
5. Save as collection for team reuse

64. Integrating Third-Party APIs in CodeIgniter

Use CI4’s HTTP client (or curl) to fetch/post data to payment, SMS, or weather providers. Keep keys in `.env`.

HTTP client GET

$client = ConfigServices::curlrequest();
$response = $client->get('https://api.example.com/data', [
    'headers' => ['Authorization' => 'Bearer ' . env('API_TOKEN')],
]);
$data = json_decode($response->getBody(), true);

65. Google Login Integration in CodeIgniter

Use Google OAuth client credentials, redirect URI, and verify the profile email before creating/logging in the user.

OAuth high-level flow

1. Redirect user to Google consent screen
2. Google returns authorization code
3. Exchange code for tokens
4. Fetch profile email
5. Create/find local user + start session

66. Payment Gateway Integration in CodeIgniter

Never trust client-only payment success. Verify signatures/webhooks server-side and update order status securely.

Payment checklist

1. Create order in DB (pending)
2. Send user to gateway checkout
3. Handle success/cancel callbacks
4. Verify webhook signature
5. Mark order paid only after verification

67. Admin Panel Development in CodeIgniter

Use route groups + auth/role filters, a dedicated admin layout, and modular controllers for users/posts/settings.

Admin route group

$routes->group('admin', ['filter' => 'auth:admin'], static function ($routes) {
    $routes->get('/', 'AdminDashboard::index');
    $routes->resource('posts', ['controller' => 'AdminPosts']);
});

68. E-commerce Project with CodeIgniter

Break the project into modules: catalog, cart session, checkout, payments, and order history.

Suggested modules

Products + categories
Cart (session)
Checkout + address
Payments + webhooks
Orders + admin fulfillment

69. Blog Management System in CodeIgniter

A blog project is ideal practice for models, pagination, slug routes, auth, and image uploads.

Blog features checklist

Post CRUD + slug URLs
Categories/tags
Featured image upload
Pagination + search
Admin-only write access

70. Deployment to Live Server (CodeIgniter)

Point the web root to `public/`, set production env, configure DB, and secure writable permissions.

Deploy checklist

1. Upload code / git pull
2. composer install --no-dev
3. Set .env production + DB
4. Document root = /public
5. php spark migrate
6. Secure writable/ permissions

71. CodeIgniter Optimization

Optimize by reducing queries, enabling cache, using pagination, and turning off debug toolbar in production.

Optimization tips

- Cache expensive queries
- Paginate large lists
- Avoid N+1 style loops/queries
- Use production environment
- Optimize images/assets

72. CodeIgniter Security Best Practices

Security is layered: validate input, escape output, hash passwords, use HTTPS, protect uploads, and keep dependencies updated.

Security checklist

- CSRF on state-changing requests
- esc() all output
- password_hash / password_verify
- Validate uploads
- Least-privilege DB user
- Secrets only in .env

73. CodeIgniter Interview Questions

Be ready to explain MVC, CI4 vs CI3, validation, sessions, migrations, and how filters work.

Sample Q&A

Q: What is MVC in CI?
A: Model=data, View=UI, Controller=request flow.

Q: What are filters?
A: Middleware-like before/after hooks.

Q: Why Query Builder?
A: Safer, readable DB queries.

Q: How do you prevent XSS?
A: Escape output with esc().

74. Final Project – CRUD + Authentication + REST API

Build one complete app: user registration/login, protected CRUD for a resource (posts/products), and a JSON API with status codes.

  1. Create migrations for users and posts.
  2. Implement registration/login.
  3. Add web CRUD + API CRUD.
  4. Protect routes with filters.
  5. Test with Postman and deploy.

Final project scope

1. Auth (register/login/logout)
2. Password hashing + session/JWT
3. Resource CRUD with validation
4. REST API endpoints + Postman tests
5. CSRF/XSS basics + flash messages
6. Deploy-ready .env + migrations

Suggested API routes

$routes->group('api', static function ($routes) {
    $routes->post('login', 'ApiAuth::login');
    $routes->resource('posts', ['controller' => 'ApiPosts', 'filter' => 'jwt']);
});

Conclusion

You now have a full CodeIgniter path: setup, MVC, forms, database, APIs, auth, and security. Practice with the final CRUD + Authentication + REST API project, then deploy with production settings.

Leave a reply

Your email address will not be published. Required fields are marked *