• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » CodeIgniter 3 to CodeIgniter 4 Migration: Upgrading Legacy Namespace-less PHP Code to Modern PSR-4 Architecture

CodeIgniter 3 to CodeIgniter 4 Migration: Upgrading Legacy Namespace-less PHP Code to Modern PSR-4 Architecture

Understanding the Core Differences: CI3 vs. CI4

Migrating from CodeIgniter 3 (CI3) to CodeIgniter 4 (CI4) is not a simple version bump; it’s a fundamental architectural shift. CI3, while robust for its time, largely operated without strict adherence to modern PHP standards like PSR-4 autoloading and namespaces. CI4, conversely, is built from the ground up with these principles, offering a more organized, maintainable, and scalable framework. The most significant change is the move from a procedural, file-based loading mechanism to a fully namespaced, Composer-driven autoloading system. This means your controllers, models, libraries, and helpers will need to be reorganized and their usage updated to reflect their new namespace paths.

Phase 1: Project Setup and Composer Integration

The first step is to set up a new CI4 project and begin migrating your existing CI3 application’s components into its structure. This involves leveraging Composer, the de facto standard for PHP dependency management.

1. Install CodeIgniter 4:

Use Composer to create a new CI4 project. It’s recommended to install it globally or use npx for a project-local installation if you prefer.

composer create-project codeigniter4/appstarter my-ci4-app
cd my-ci4-app

2. Configure Autoloading (PSR-4):

CI4’s app/Config/Autoload.php file is crucial. It defines how your application’s classes are loaded. You’ll need to map your existing CI3 application’s directories to namespaces. For instance, if your CI3 application had a libraries folder containing custom classes, you’ll map this to a namespace.

<?php

namespace Config;

use CodeIgniter\Config\AutoloadConfig;

/**
 * Autoloading Configuration
 *
 * This configuration file defines the namespaces and paths for the
 * autoloader.
 */
class Autoload extends AutoloadConfig
{
    /**
     * An array of namespaces and their relative paths.
     *
     * The keys are the names of the namespaces, and the values are the
     * paths to the directories that contain the classes for those namespaces.
     *
     * @var array<string, string>
     */
    public $psr4 = [
        APP_NAMESPACE => APPPATH, // Core CI4 namespace
        'Config'      => APPPATH . 'Config',
        // Add your custom namespaces here
        'App\Libraries' => APPPATH . 'Libraries', // Example: Mapping CI3 libraries
        'App\Models'    => APPPATH . 'Models',    // Example: Mapping CI3 models
        'App\Helpers'   => APPPATH . 'Helpers',   // Example: Mapping CI3 helpers
    ];

    /**
     * An array of files that will be included at the beginning of
     * each script.
     *
     * @var array<string, string>
     */
    public $files = [];

    /**
     * An array of directories that will be scanned for models.
     *
     * @var array<string, string>
     */
    public $classmap = [];

    /**
     * An array of files that will be included once.
     *
     * @var array<string, string>
     */
    public $registerProperties = [];
}

3. Migrate CI3 Files to CI4 Structure:

Copy your CI3 application’s core files (controllers, models, libraries, helpers) into the corresponding new directories within your CI4 project’s app/ folder. For example:

  • CI3 application/controllers/ -> CI4 app/Controllers/
  • CI3 application/models/ -> CI4 app/Models/
  • CI3 application/libraries/ -> CI4 app/Libraries/
  • CI3 application/helpers/ -> CI4 app/Helpers/

Ensure the directory structure within these new locations aligns with the namespaces you’ve defined in Autoload.php. For instance, if you have app/Libraries/MyLib.php, its namespace should be App\Libraries.

Phase 2: Namespace and Class Refactoring

This is the most labor-intensive part of the migration. Every class that was previously loaded implicitly by CI3 now needs to be explicitly referenced using its namespace and the use statement.

1. Add Namespaces to Your Classes:

At the top of each of your migrated PHP files, add the appropriate namespace declaration. This must match the mapping in app/Config/Autoload.php.

// app/Libraries/MyLib.php
<?php

namespace App\Libraries; // Matches the PSR-4 mapping

class MyLib
{
    public function doSomething()
    {
        return "Hello from MyLib!";
    }
}

2. Update Class Instantiation and Usage:

In your controllers and other classes, you’ll need to use the use statement to import the classes you need and then instantiate them directly. The CI3 `$this->load->library(‘MyLib’)` pattern is replaced by standard PHP object instantiation.

// app/Controllers/Home.php
<php

namespace App\Controllers;

// Import the library using its namespace
use App\Libraries\MyLib;

class Home extends BaseController
{
    public function index()
    {
        // Instantiate the library directly
        $myLib = new MyLib();
        $data['message'] = $myLib->doSomething();

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

3. Migrating Models:

CI4 models are typically extended from CodeIgniter\Model. You’ll need to update your model files to include the namespace and extend the base model class. The database connection is managed differently; you’ll usually inject it or use the built-in connection manager.

// app/Models/UserModel.php
<?php

namespace App\Models;

use CodeIgniter\Model;

class UserModel extends Model
{
    protected $table      = 'users';
    protected $primaryKey = 'id';

    protected $allowedFields = ['name', 'email'];

    // ... other model properties and methods
}

In your controller, you would then instantiate it like so:

// app/Controllers/UserController.php
<?php

namespace App\Controllers;

use App\Models\UserModel; // Import the model

class UserController extends BaseController
{
    public function listUsers()
    {
        $userModel = new UserModel(); // Instantiate the model
        $data['users'] = $userModel->findAll();

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

4. Migrating Helpers:

CI4 helpers are also namespaced. You’ll need to declare the namespace and then call helper functions directly. CI4 also encourages the use of Services for common functionalities, which can sometimes replace the need for custom helpers.

// app/Helpers/custom_helper.php
<?php

namespace App\Helpers;

if (! function_exists('my_custom_function')) {
    function my_custom_function($param)
    {
        return "Processed: " . strtoupper($param);
    }
}

In your controller:

// app/Controllers/ExampleController.php
<?php

namespace App\Controllers;

// No explicit 'use' needed for functions in the App\Helpers namespace if autoloaded correctly.
// However, for clarity or if not automatically loaded, you might ensure it's loaded via Services or Config.

class ExampleController extends BaseController
{
    public function processData()
    {
        $result = my_custom_function('some_data'); // Call the helper function directly
        echo $result;
    }
}

Ensure your app/Config/Autoload.php has the correct mapping for your helpers directory, e.g., 'App\Helpers' => APPPATH . 'Helpers',. CI4’s autoloader will then find and load these functions.

Phase 3: Configuration and Routing Adjustments

CI4’s configuration and routing systems are significantly different. Configuration values are managed in app/Config/ files, and routing is more explicit.

1. Configuration Files:

CI3’s application/config/config.php and other config files are replaced by individual configuration classes in app/Config/. For example, database settings are in app/Config/Database.php, and general app settings are in app/Config/App.php.

// app/Config/App.php
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
    // ... other settings
    public $baseURL = 'http://localhost:8080/';
    public $indexPage = '';
    public $defaultLocale = 'en';
    // ...
}

You’ll need to port your custom configuration values from CI3’s config files to new, dedicated config classes in CI4, or add them to the existing ones. You can then access these values via the Services API:

// In a controller or library
$config = config('App'); // Access the App config class
echo $config->baseURL;

$dbConfig = config('Database'); // Access the Database config class
// Use $dbConfig for database connection settings

2. Routing:

CI4 uses a dedicated routing file, app/Config/Routes.php, which is much more powerful and explicit. You’ll need to redefine your routes here. The old $route[...] array syntax is gone.

// app/Config/Routes.php
<?php

use CodeIgniter\Router\RouteCollection;

/**
 * @var RouteCollection $routes
 */
$routes->get('/', 'Home::index');

// Example: Migrating a CI3 route like $route['users/(:num)'] = 'users/profile/$1';
$routes->get('users/(:num)', 'UserController::profile/$1');

// Example: Migrating a CI3 route with a controller and method like $route['admin/dashboard'] = 'admin/dashboard';
$routes->get('admin/dashboard', 'Admin\DashboardController::index'); // Assuming Admin namespace for controllers

// Example: Catch-all route
$routes->get('(:any)', 'NotFoundController::show');

Notice the use of namespaces in routes, e.g., Admin\DashboardController. This aligns with the PSR-4 structure.

Phase 4: Handling Libraries, Helpers, and Core Changes

Several core functionalities and patterns have changed, requiring careful adaptation.

1. CI3 Libraries vs. CI4 Services:

Many CI3 libraries (like email, session, pagination) are now available as “Services” in CI4. You access them via the service() function. This is a more robust and flexible way to manage shared resources.

// CI3: $this->email->from(...);
// CI4:
$email = \Config\Services::email();
$email->setFrom('[email protected]', 'Sender Name');
$email->setTo('[email protected]');
// ...
$email->send();

2. CI3 Hooks vs. CI4 Filters:

CI3’s hook system for extending core functionality is replaced by CI4’s “Filters.” Filters are classes that can run before or after controller execution, offering a more structured approach to tasks like authentication, authorization, or request manipulation.

// app/Config/Filters.php
<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class Filters extends BaseConfig
{
    // ...

    public $aliases = [
        'csrf'     => \CodeIgniter\Filters\CSRF::class,
        'toolbar'  => \CodeIgniter\Filters\DebugToolbar::class,
        'honeypot' => \CodeIgniter\Filters\Honeypot::class,
        'auth'     => \App\Filters\AuthFilter::class, // Your custom auth filter
    ];

    public $methods = [];
    public $filters = [
        'auth' => ['before' => ['admin/*']], // Apply auth filter to all routes under /admin/
    ];
}

You would then create app/Filters/AuthFilter.php:

// app/Filters/AuthFilter.php
<?php

namespace App\Filters;

use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;

class AuthFilter implements FilterInterface
{
    public function before(RequestInterface $request, $arguments = null)
    {
        // If user is not logged in, redirect to login page
        if (! session()->get('isLoggedIn')) {
            return redirect()->to('/login');
        }
    }

    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {
        // Do something after the controller
    }
}

3. Database Abstraction:

CI4’s database layer is more modern. While it still supports query builders and direct SQL, it also integrates better with ORM patterns via the CodeIgniter\Model class. Ensure your database connection details are correctly set in app/Config/Database.php.

Phase 5: Testing and Debugging

Thorough testing is paramount. CI4 comes with built-in testing tools that leverage PHPUnit.

1. Enable Development Mode:

For debugging, ensure your environment is set to development. This is typically done via an .env file in the project root.

# .env file
CI_ENVIRONMENT = development

This will enable the Debug Toolbar and detailed error reporting.

2. Unit and Feature Testing:

Write tests for your refactored controllers, models, and libraries. CI4 provides a testing framework that makes this straightforward. You can run tests from the command line:

php spark test:run

3. Debugging Tools:

Leverage the built-in Debug Toolbar, which provides insights into database queries, loaded files, memory usage, and more. For deeper debugging, use standard PHP debugging techniques like var_dump(), print_r(), or a debugger like Xdebug.

Key Takeaways for a Smooth Migration

  • Embrace Namespaces: This is the biggest shift. All your classes must be namespaced and autoloaded via PSR-4.
  • Composer is King: CI4 is Composer-native. Manage dependencies and autoloading through it.
  • Services over Libraries: Understand how CI4’s Services replace many CI3 libraries.
  • Filters for Hooks: Adapt your CI3 hook logic to CI4’s Filter system.
  • Configuration Restructuring: Port your CI3 configurations to CI4’s dedicated config classes.
  • Routing Redefinition: Rewrite your routes using the CI4 routing file.
  • Incremental Migration: For very large applications, consider migrating module by module or feature by feature, rather than a “big bang” approach.

The migration from CodeIgniter 3 to CodeIgniter 4 is a significant undertaking, but it’s essential for leveraging modern PHP practices, improving maintainability, and accessing the latest features and security updates. By systematically addressing namespaces, autoloading, configuration, and core architectural changes, you can successfully upgrade your legacy application to a robust, modern framework.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability
  • Scala Pekko vs. Go Goroutines: Actor Model vs. CSP for Event-Driven Reactive Systems
  • Java Loom Virtual Threads vs. Go Goroutines: Under-the-Hood Scheduler and Thread Overhead Comparison

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (584)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (806)
  • PHP (5)
  • PHP Development (21)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (19)
  • Ruby on Rails (1)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (357)

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (806)
  • Debugging & Troubleshooting (584)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala