Building a Legacy PHP Development Environment: PHP 5.3.28 + CodeIgniter 2.1.0 + SQL Server 2022

I decided to use Claude.AI to help me to get a project skeleton put in place that would allow me to work on a legacy CodeIgniter 2.1.0 project on PHP 5.3 using SQL Server 2022. Back in 2022 I was able to get a configuration of this up and running by hunting and pecking on the web and it took me the better part of a day and a half to get to that point. I figured that this might be a good task for Claude.AI to help with.

It turns out it was a good idea to work with Claude.AI - we were able to put a solution together in about 3 hours that should enable me to actually work on the project. After I get things tested and working I stored it in a Github repository and asked Claude.AI to write a summary of what was built. That summary follows.

The Challenge

Recently, I needed to set up a development environment for maintaining a legacy PHP application. The requirements were specific and somewhat challenging:

  • PHP 5.3.28 (released in 2012, now EOL)
  • CodeIgniter 2.1.0 (legacy framework version)
  • SQL Server 2022 (modern database)
  • Docker-based for easy deployment and consistency
  • Volume mounts for live development without rebuilds
  • macOS development with modern tooling (uv for Python)

The main challenge? Getting ancient PHP to talk to modern SQL Server, all while maintaining a smooth development workflow.

The Solution: Docker + FreeTDS + Volume Mounts

Architecture Overview

The final setup consists of two Docker containers:

  1. PHP Container: Ubuntu 14.04 with PHP 5.3.28, Apache2, and FreeTDS
  2. SQL Server Container: Microsoft SQL Server 2022

Key Technical Decisions

1. FreeTDS for Database Connectivity

Microsoft’s official SQL Server drivers (SQLSRV) require PHP 7.0+, so we used FreeTDS - an open-source implementation of the TDS protocol. The connection flow:

PHP Application → PDO → pdo_dblib → FreeTDS → TDS Protocol → SQL Server

FreeTDS bridges the 13-year gap between PHP 5.3 and SQL Server 2022 by translating the TDS protocol version 8.0.

2. Volume Mounts for Live Development

Instead of baking the application into the Docker image, we mounted the local ./app/ directory:

volumes:
  - ./app:/var/www/html/codeigniter

This means: - Edit code locally with your favorite IDE - Changes appear instantly in the container - No Docker rebuilds for code changes - Only rebuild when modifying system dependencies

3. Database Initialization Challenges

SQL Server 2022 containers don’t include sqlcmd by default, and the path changed from /opt/mssql-tools/bin/sqlcmd to /opt/mssql-tools18/bin/sqlcmd.

Solution? A Python script with smart fallbacks: 1. Try Python with pyodbc (most reliable) 2. Auto-detect sqlcmd path if available 3. Support both uv (modern Python manager) and standard pip

4. Modern Tooling on macOS

The setup script auto-detects uv and creates a proper virtual environment:

# Automatically creates .venv/ and installs dependencies
./setup.sh

# Use the environment
uv run python init_db.py

The Development Workflow

Initial Setup

chmod +x setup.sh
./setup.sh

This single command: - Downloads CodeIgniter 2.1.0 - Creates Python virtual environment (if using uv) - Builds and starts Docker containers - Initializes SQL Server with test data - Configures CodeIgniter for SQL Server connectivity

Daily Development

# Start containers
docker-compose up -d

# Edit code in ./app/ directory
vim ./app/application/controllers/welcome.php

# Refresh browser - changes are live!

# Stop containers
docker-compose down

No rebuilds. No copying files. Just edit and refresh.

Technical Hurdles Solved

1. Missing PDO_DBLIB Extension

Problem: PHP couldn’t connect to SQL Server - pdo_dblib.so wasn’t loading.

Solution: Install php5-sybase package which provides the proper FreeTDS-backed PDO driver.

2. Apache Configuration for CodeIgniter

Problem: URLs like /index.php/test returned 404 errors.

Solution: - Configure Apache with AllowOverride All - Create .htaccess with mod_rewrite rules - Set correct DirectoryIndex - Use Apache 2.4.7 syntax (Order allow,deny instead of Require all granted)

3. Python Environment Management

Problem: uv requires either a virtual environment or --system flag.

Solution: Automatically create and use a .venv/ directory, following Python best practices.

4. Database Initialization Reliability

Problem: sqlcmd path varies by SQL Server version and isn’t always available.

Solution: Multi-method approach with smart detection:

# Method 1: Python + pyodbc (most reliable)
uv run python init_db.py

# Method 2: Auto-detect sqlcmd location
# /opt/mssql-tools18/bin/sqlcmd (2022)
# /opt/mssql-tools/bin/sqlcmd (older)

Project Structure

your-project/
├── app/                    # ← Your CodeIgniter application (volume mounted)
│   ├── application/
│   │   ├── controllers/
│   │   ├── models/
│   │   ├── views/
│   │   └── config/
│   ├── system/
│   └── index.php
├── .venv/                  # Python virtual environment (auto-created)
├── Dockerfile              # PHP 5.3 + FreeTDS setup
├── docker-compose.yml      # Container orchestration
├── setup.sh                # One-command setup script
├── init_db.py              # Database initialization (Python)
├── init-db.sql             # Database initialization (SQL)
└── README.md               # Comprehensive documentation

Final Thoughts

Building a development environment that bridges 13 years of technology evolution required creative solutions:

  • FreeTDS bridges the gap between ancient PHP and modern SQL Server
  • Volume mounts provide instant feedback for development
  • Smart initialization handles multiple SQL Server versions
  • Modern tooling (uv, virtual environments) makes it maintainable
  • Comprehensive documentation ensures the setup is reproducible

While PHP 5.3 and Ubuntu 14.04 are long past end-of-life and should never be used in production, sometimes maintaining legacy applications is a business necessity. This setup provides a consistent, reproducible development environment that works on any machine with Docker.

The key lesson? Even ancient technology can benefit from modern DevOps practices. Volume mounts, containerization, and good documentation make legacy maintenance significantly less painful.

Resources


Note: This setup is strictly for maintaining legacy applications. For new projects, please use modern versions of PHP (8.x), CodeIgniter (4.x), and follow current security best practices.