LLegacy Lift

Guide · 2026

How to Maintain and Modernise Legacy PHP in 2026

PHP still powers a huge share of the web — and a lot of it is old. If you’ve inherited a WordPress site, a CodeIgniter app, or a folder of raw .php files with no documentation, this guide gives you a concrete plan to understand it, secure it, and bring it forward — without a risky big-bang rewrite.

Why legacy PHP is worth maintaining, not abandoning

Roughly three out of four websites with a known server-side language still run PHP. Most of that is not greenfield Laravel — it’s years-old WordPress, bespoke procedural code, and early-framework apps that quietly run real businesses. For Indian SMBs and agencies, these apps generate revenue today. A rewrite is expensive, slow, and risky. The pragmatic move in 2026 is to maintain and incrementally modernise.

The blocker is almost always the same: nobody documented it, the original developer is gone, and you’re afraid to touch it. So step one is not coding — it’s understanding.

Step 1 — Map the codebase before you change anything

Get answers to these questions first:

  • What framework (if any)? WordPress, Laravel, CodeIgniter, Symfony, Drupal, or raw PHP each imply different idioms and risks.
  • Where are the entry points? In raw PHP every file may be directly reachable over HTTP — a security concern modern frameworks avoid with a single front controller.
  • Where does data flow? Find the database layer, the auth code, and any file uploads.

You can do this by hand, or paste the code into a tool like Legacy Lift to get an architecture summary, framework detection, and a ranked list of issues in seconds.

Step 2 — Fix the critical security issues

Legacy PHP has a recognisable set of high-severity footguns. Hunt these down first:

SQL injection from string concatenation

The classic: mysql_query("SELECT * FROM users WHERE name='" . $_POST['u'] . "'"). Any query that interpolates request data is exploitable. Replace with prepared statements using PDO:

$stmt = $pdo->prepare('SELECT * FROM users WHERE name = ?');
$stmt->execute([$_POST['u']]);
$user = $stmt->fetch();

Removed mysql_* functions

The original mysql_* extension was removed in PHP 7 (2015). Any code still usingmysql_connect() / mysql_query() will fatal-error on a modern runtime. Migrate to PDO (recommended) or mysqli, and use bound parameters everywhere.

File inclusion, eval, and command execution

include($_GET['page']) is local/remote file inclusion. eval() andsystem() on variable input are remote code execution. Remove these patterns: whitelist allowed pages to fixed paths, delete eval(), and avoid shelling out — or at minimum use escapeshellarg() with a strict allowlist.

Weak password hashing and XSS

md5($password) is not acceptable for passwords — use password_hash() and password_verify(). And anywhere request data is echoed into HTML, escape it with htmlspecialchars($v, ENT_QUOTES, 'UTF-8') to stop reflected XSS.

Step 3 — Stabilise the foundation

  1. Pin a supported PHP version. PHP 8.1 reaches end of life; target PHP 8.2+ (ideally 8.3/8.4). Each major release brings real performance and security gains.
  2. Adopt Composer + autoloading. Even for old code, a composer.json with PSR-4 autoloading lets you stop using manual require chains and pull in maintained libraries.
  3. Add version control and a .gitignore if the project somehow isn’t in git yet. Never commit credentials.
  4. Move secrets to environment variables. Hardcoded DB passwords in PHP files are both a security and an ops problem.

Step 4 — Add a safety net before refactoring

You cannot safely refactor code you can’t verify. Before restructuring, add a thin layer of tests around the most important flows — login, checkout, data writes. Even a handful of end-to-end tests with PHPUnit or a tool like Pest catches regressions when you start moving logic out of templates into classes.

Step 5 — Modernise incrementally (the strangler pattern)

Resist the rewrite. Instead, wrap the legacy app and replace it piece by piece:

  • Put the old app behind a router or front controller so you control entry points.
  • Extract business logic out of mixed PHP/HTML files into testable service classes.
  • Introduce a query builder or ORM (Eloquent, Doctrine) module by module.
  • Where a section is fully understood and tested, rewrite just that section in modern PHP — or a modern framework — behind the same URL.

This keeps the business running while the codebase steadily improves. There is no day where everything breaks.

A realistic 30-day plan

  1. Days 1–3: Map architecture and run a security scan. Document entry points and the data layer.
  2. Days 4–10: Fix all critical and high findings (SQLi, inclusion, eval, weak hashing).
  3. Days 11–15: Upgrade to PHP 8.2+, add Composer, move secrets to env.
  4. Days 16–22: Add tests around login and the top revenue flow.
  5. Days 23–30: Extract one module into clean, tested code as a template for the rest.

Get a head start

The hardest part is the first map. Legacy Liftreads your PHP and returns the architecture overview, a ranked security report with concrete fixes, and a modernisation roadmap — free for up to five files. It’s purpose-built for exactly the legacy WordPress / Laravel / raw-PHP situations described here.

Scan your legacy PHP now

Architecture, security findings, and a plan — in seconds.

Run a free scan →