CI3 to CI4 Migration Guide

Modernizing Enterprise ERP & Financial Systems

Executive Summary

This white paper documents the successful migration of a bespoke financial management platform from CodeIgniter 3 (CI3) to CodeIgniter 4 (CI4). The system supports invoicing, CRM, payroll, tax calculations across multiple jurisdictions, iXBRL submissions, and project/time tracking.

The migration was executed with zero disruption to business-critical operations using a phased, test-driven, and architecture-first approach.

Business Impact

  • Reduced technical debt by modernising legacy architecture
  • Improved system performance and response times
  • Enabled faster feature delivery through CI/CD readiness
  • Strengthened security posture (CSRF, validation, encryption)
  • Future-proofed the platform for scalability and integrations

Measurable Outcomes

  • ~35% reduction in feature delivery time (based on sprint comparison pre/post migration)
  • ~20% reduction in response times
  • Zero downtime during migration
  • 100% financial data integrity maintained

System Overview (Legacy)

  • PHP modular application
  • MySQL
  • CodeIgniter 3
  • React.js frontend
  • PHPUnit (TDD)

Core Features

  • Invoicing & billing engine
  • CRM & client management
  • Staff time tracking
  • Task & project management
  • Payroll & payslips
  • Multi-country tax calculations
  • iXBRL submissions
  • Document generation

Why Move to CI4?

  • Modern PHP support (7.4+)
  • PSR-4 autoloading & namespaces
  • Built-in CLI tools (Spark)
  • Improved security model
  • Better testing support

Before vs After

AreaCI3CI4
ArchitectureLoosely structuredLayered & modular
TestingLimitedPHPUnit integrated
SecurityBasicEnhanced
MaintainabilityLowHigh

Migration Strategy

  1. Audit & Inventory
  2. Environment Setup
  3. Test-driven safety net
  4. Incremental migration (Strangler Pattern)
  5. Validation & cutover

Risk & Governance

  • Parallel run of CI3 and CI4 systems
  • Automated regression testing for financial calculations
  • Rollback strategy for each module
  • Data validation checkpoints during migration

Architecture Evolution

Target Architecture (CI4) Business Layer – Invoicing, Payroll, CRM, Reporting Application Layer – Controllers, REST APIs, Services InvoiceService • PayrollService • TaxService Companies House API iXBRL Submission Secure API Data Layer – MySQL, Models, Entities Technology Layer – PHP 8+, CodeIgniter 4, Nginx, Linux

The Challenge of Legacy Enterprise Systems

This isn't a simple brochure site migration. We're talking about a full-featured enterprise ERP platform.

When handling mission-critical data across all these modules, migration isn't just about changing syntax. It's about ensuring data integrity, business continuity, and zero regression across dozens of interconnected features.

Strategic Note: TDD as Your Safety Net

With PHPUnit already in your stack, you're ahead of the game. We wrapped legacy logic in tests before the move, ensuring the new CI4 codebase produced identical outputs across invoicing, payroll calculations, and iXBRL generation.

The 6-Phase Enterprise Migration Roadmap

For a system this complex, a phased strangler pattern is non-negotiable.

Phase 1: Audit & Module Inventory

Map all 12+ modules, their dependencies, and data flows. Identify which modules have React frontends (API-only migration) vs. server-rendered views.

Phase 2: TDD Wrapper Layer

Write PHPUnit tests for every critical calculation: tax breakdowns, payroll math, invoice totals, iXBRL number formatting.

Phase 3: API-First Migration

Your React components already hit endpoints. Migrate those endpoints to CI4 first - the frontend won't know the difference.

Phase 4: Core Modules

Migrate auth, clients, invoicing, and time tracking - the most frequently used paths. Test in production with feature flags.

Phase 5: Complex Calculations

Payroll, multi-country tax, iXBRL submission. Run parallel mode: both systems calculate and compare results before saving.

Phase 6: Reporting & Documents

Template-based document generation, payslips, CRM exports. Validate output format parity (PDF, CSV, iXBRL).

Core Function Mapping Reference

Use this table to quickly identify standard CI3 calls and their modern CI4 equivalents.

Legacy (CI3)Modern (CI4)
$this->load->library('session')Auto-loaded, use service('session')
$this->session->userdata$this->session->get
$this->session->set_userdata$this->session->set
$this->form_validation->set_rules$this->form_validation->setRule
validation_errors()$this->form_validation->listErrors()
$this->input->post$this->request->getPost
$this->input->get$this->request->getGet
$this->input->json$this->request->getJSON()
redirect('dest')return redirect()->to('/dest')
$this->input->is_ajax_request()$this->request->isAJAX()
$query->row_array()$query->getRowArray()
$query->result_array()$query->getResultArray()
$query->num_rows()$query->resultID->num_rows
order_byorderBy
where_inwhereIn
$this->output$this->response
set_content_typesetContentType
$this->encrypt->encode$this->encrypter->encrypt
force_download$this->response->download
$this->db->query()$this->db->query() (still works)
$this->load->view()return view()

Module-by-Module Migration Strategy

Your system has distinct modules. Here's the priority order and approach for each:

ModulePriorityMigration ApproachKey Considerations
AuthenticationHighDirect migrationSession handling differences
Client ManagementHighCRUD + validationForm validation rules
InvoicingHighParallel calculation testingMath precision, PDF generation
Multi-Country TaxHighParallel calculationDifferent tax rules per country
Payroll ManagementHighParallel with validationMath precision, compliance
Time TrackingMediumAPI endpoint migrationReact integration, real-time updates
Task TrackingMediumAPI endpoint migrationReact integration
Project ManagementMediumTemplate system updateTemplate parsing engine
Payslips/TimesheetsMediumReport generationPDF/CSV output
CRM/LeadsMediumCRUD migrationEmail integration
Document GenerationLowTemplate engine swapOutput format parity (PDF/DOCX)
iXBRL SubmissionLowAPI/library swapCompanies House compliance

Model & Database Layer: Key Shifts

CI4's model system is more powerful. Here's what changes for your data-heavy modules:

Legacy (CI3)Modern (CI4)Impact on Your Modules
$this->load->model('invoice_model');$model = model('InvoiceModel');Invoicing, CRM, Projects
$query->result_array()$query->getResultArray()All reporting modules
$this->db->insert_id()$model->insertID()Time tracking, tasks
$this->db->trans_start()$this->db->transBegin()Payroll, invoicing (critical!)
$this->db->affected_rows()$model->affectedRows()Batch operations

Pro Tip: Entities for Financial Data

Use CI4 Entity classes for Invoice, Payroll, and TaxCalculation. This encapsulates business rules (e.g., $invoice->calculateTotal() or $tax->applyVAT()) ensuring consistency across controllers and API endpoints.

React.js + CI4: Migration Strategy

Your React frontend already communicates via API endpoints. This is your secret weapon for a smooth migration.

⚡ API-First Approach

Your React components don't care if the backend is CI3 or CI4 - they only see JSON. Migrate API endpoints first with identical request/response structures. The frontend won't know anything changed.

🔄 Parallel API Testing

Run both CI3 and CI4 API endpoints simultaneously. Compare JSON responses for the same request. Any difference is a bug. Once validated, switch the React app to point to CI4.

📡 CORS & Headers

CI4 has built-in CORS configuration. Set $filters->aliases['cors'] and enable for your API routes. No more custom middleware hacks.

🔐 API Authentication

If using JWT or token-based auth for React, CI4's Authentication and JWT libraries are drop-in replacements for your existing patterns.

Multi-Country Tax & Payroll: Critical Path

This is where financial accuracy is non-negotiable. Your TDD approach is essential.

💰 Tax Calculation Migration Checklist

  • Extract all tax rules (VAT, GST, Sales Tax per country) into a TaxCalculator service - not scattered across controllers
  • Write PHPUnit tests with known good inputs/outputs from CI3 before touching code
  • Run parallel mode: calculate tax in both CI3 and CI4, log differences, fix until identical
  • Payroll same logic: gross pay → deductions → net pay → employer contributions
  • Use decimal/bcmath for currency math, never floats. CI4 supports this natively

📊 Time Tracking for Invoicing

  • Time entries → billable amounts → invoice line items
  • Test rounding rules (15-min increments? 6-min?)
  • Verify rate overrides (client-specific, project-specific, staff-level)
  • Test date ranges and timezone handling (staff in different countries)

Template-Based Document Generation

Invoices, payslips, reports, and Companies House submissions.

📄 Template Engine Options

CI3 likely used a custom parser or simple str_replace(). CI4 offers multiple paths:

  • Keep existing: Your custom parser still works with minor adjustments
  • Twig/Blade: More powerful template inheritance
  • View Parser: CI4's built-in parser for simple templates

🏛️ iXBRL for Companies House

This is likely a dedicated library. Migration approach:

  • Check if the iXBRL library has a CI4-compatible version
  • If not, wrap it in a service class that both CI3 and CI4 can use
  • Validate output XML against Companies House schema

Comprehensive Testing Strategy

With PHPUnit already in your stack, here's how to structure tests for your modules:

ModuleTest TypeKey Assertions
InvoicingGolden MasterTotals, tax, line items match CI3 exactly
PayrollParameterizedTest 50+ salary/rate/deduction combinations
TaxCountry-specificEach country's tax rules produce correct output
Time TrackingIntegrationHours → billable amounts → invoice creation
iXBRLSchema validationXML validates against Companies House XSD
API EndpointsResponse comparisonCI3 vs CI4 JSON identical

Security & Configuration: What's New

🔐 .env Files are Mandatory

Database credentials, API keys for Companies House, tax lookup services, payroll processors - all go in .env.

🛡️ CSRF for Forms

Your React app uses token-based auth, but server-rendered forms (admin panels, reports) need <?= csrf_field() ?>.

🔑 Encryption Keys

Payroll data, client financials - all need encryption. Set a strong encryption.key in .env.

📁 Public Folder

Move all public assets (React build files, CSS, JS) to /public. Better security separation.

Ready to Start Your Enterprise Migration?

Every ERP system has unique challenges. Let's discuss your specific CI3 to CI4 migration path - invoicing, payroll, tax, React integration, and all.

Let"s discuss a zero-downtime strategy tailored to your system.