← All articles
June 24, 2026

Inheriting a Legacy PHP Site With No Documentation: Where to Start

The original developer is gone. There's no README, no version control, no comments. The site is running on PHP 5.6 and your client needs it to keep working. Here's how to approach this.

This Is More Common Than You Think

Almost every freelance developer eventually inherits a legacy project. No documentation. No git history. PHP 5.6 or 7.0. MySQL queries directly in template files. A folder called final_FINAL_v3_use_this.

The client doesn't want a rewrite — they just want it to not break. Here's how to approach it professionally.

Step 1: Don't Touch Anything Yet

Before you change a single file:

  1. Take a full backup — files and database. Download everything via FTP. Export the database with mysqldump.
  2. Set up a staging copy — clone the site to a subdomain or local environment. Do all work there first.
  3. Enable error logging — not display, just logging. You want to see what's already broken.
// Add to the top of the main index.php or config
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/error.log');
error_reporting(E_ALL);

Step 2: Map the Site

Spend 30–60 minutes just understanding the structure before writing code.

# Count PHP files
find . -name "*.php" | wc -l

# Find the entry points
find . -name "index.php" | head -20

# Find config files (often contain DB credentials and settings)
find . -name "config.php" -o -name "settings.php" -o -name "configuration.php"

# Find files modified recently (signs of recent work or active editing)
find . -name "*.php" -mtime -30 | sort

Look for:

  • Where the database connection is established
  • Whether there's a framework (CodeIgniter, custom MVC, or no framework at all)
  • What the URL routing looks like (mod_rewrite rules in .htaccess?)
  • Whether there's a templating system or raw PHP in HTML

Step 3: Understand the Database

-- List all tables with row counts
SELECT table_name, table_rows
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY table_rows DESC;

-- Find the core tables (users, orders, products, etc.)
SHOW TABLES;

Look at the biggest tables — that's where the important data lives. Check a few rows to understand the data model.

Step 4: Identify What's Actually Breaking

Check the error log you just enabled. Most legacy sites have a backlog of warnings — not all of them matter. Prioritise:

  • Fatal errors — things that crash pages
  • Deprecated function calls — these become fatal on PHP 8
  • Database errors — failed queries, connection issues
# Count error types in the log
grep "Fatal error" error.log | wc -l
grep "Deprecated" error.log | sort | uniq -c | sort -rn | head -20
grep "Warning" error.log | sort | uniq -c | sort -rn | head -20

Step 5: Create a Safety Net Before Changing Anything

Legacy code has no tests. That means any change can break something you didn't expect.

Minimal safety net:

  1. List the most important pages/flows (homepage, login, checkout, key forms)
  2. Document what "working" looks like for each (manually, with screenshots if needed)
  3. After every change, manually verify each key flow still works

For anything more complex, a simple smoke test script helps:

// smoke_test.php — run after each change
$pages = [
    "/",
    "/login",
    "/products",
    "/cart",
    "/checkout",
];

foreach ($pages as $page) {
    $url = "http://localhost" . $page;
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $body = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    echo ($status === 200 ? "✓" : "✗") . " [{$status}] {$page}
";
}

Step 6: Fix in Order of Impact

Priority order for a legacy PHP site:

  1. Security — SQL injection, exposed credentials, file upload vulnerabilities. Non-negotiable.
  2. Fatal errors — things that crash. Fix these first.
  3. PHP compatibility — if a version upgrade is required, run phpcs to list all issues
  4. Deprecated warnings — clean these up systematically, they become fatals on PHP 8
  5. Performance — only after the above are stable

Common Security Issues in Legacy PHP

// VULNERABLE — SQL injection
$id = $_GET['id'];
$q = mysql_query("SELECT * FROM users WHERE id = $id");

// FIXED — parameterized query
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]);
// VULNERABLE — XSS
echo "Hello " . $_GET['name'];

// FIXED
echo "Hello " . htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');
// VULNERABLE — file path traversal
include $_GET['page'] . '.php';

// FIXED — whitelist allowed pages
$allowed = ['home', 'about', 'contact'];
$page = in_array($_GET['page'], $allowed) ? $_GET['page'] : 'home';
include $page . '.php';

Deciding Whether to Rewrite

The question always comes up. My rule of thumb:

Fix and maintain if:

  • The site is working and just needs to survive a PHP upgrade
  • Business logic is complex and well-tested by years of production use
  • Budget is limited

Rewrite if:

  • Security vulnerabilities are fundamental to the architecture (can't be patched)
  • The site needs new features that are impossible to add cleanly
  • The codebase is so tangled that every fix breaks two other things

Most legacy sites I see are worth maintaining, not rewriting. The rewrite estimate is always 3× what the client expects, and it takes 6 months instead of 6 weeks.

What I Charge for Legacy Work

Audit (understand the codebase and produce a prioritised issue list): $100–200 depending on size.

PHP 7→8 migration: $200–500 for a typical site, more for large customised platforms.

Ongoing maintenance retainer: $100–200/month for small sites (fix issues as they arise, monitor for errors).

If you've inherited something that needs to keep running and you're not sure where to start, describe what you're dealing with and I'll tell you what makes sense.

Need help with this?

DevCev Digital specialises in exactly this kind of work. Tell us what you need — we'll respond within a few hours.

Get free diagnostic →PHP Bug Fix & Legacy Code
← Back to blogGot a project? Let's talk →