Це більш поширено, ніж ви думаєте
Майже кожен фріланс-розробник рано чи пізно отримує застарілий проєкт. Жодної документації. Жодної історії git. PHP 5.6 або 7.0. MySQL-запити безпосередньо в файлах шаблонів. Папка з назвою final_FINAL_v3_use_this.
Клієнт не хоче переписувати — він просто хоче, щоб воно не ламалося. Ось як підійти до цього професійно.
Крок 1: Поки нічого не чіпайте
Перш ніж змінювати хоч один файл:
- Зробіть повне резервне копіювання — файли та базу даних. Завантажте все через FTP. Експортуйте базу даних за допомогою
mysqldump. - Налаштуйте копію для тестування — клонуйте сайт на піддомен або локальне середовище. Всю роботу виконуйте спочатку там.
- Увімкніть логування помилок — не показ, тільки запис у журнал. Ви хочете побачити, що вже зламано.
// Додайте на початок головного index.php або конфігураційного файлу
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/error.log');
error_reporting(E_ALL);
Крок 2: Складіть карту сайту
Витратьте 30–60 хвилин просто на розуміння структури, перш ніж писати код.
# Підрахувати файли PHP
find . -name "*.php" | wc -l
# Знайти точки входу
find . -name "index.php" | head -20
# Знайти конфігураційні файли (часто містять облікові дані БД та налаштування)
find . -name "config.php" -o -name "settings.php" -o -name "configuration.php"
# Знайти нещодавно змінені файли (ознаки недавньої роботи або активного редагування)
find . -name "*.php" -mtime -30 | sort
Шукайте:
- Де встановлюється з'єднання з базою даних
- Чи є фреймворк (CodeIgniter, власний MVC, або взагалі без фреймворку)
- Як виглядає маршрутизація URL (правила mod_rewrite у .htaccess?)
- Чи є система шаблонів, чи необроблений PHP у HTML
Крок 3: Зрозумійте базу даних
-- Список усіх таблиць з кількістю рядків
SELECT table_name, table_rows
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY table_rows DESC;
-- Знайти основні таблиці (користувачі, замовлення, товари тощо)
SHOW TABLES;
Подивіться на найбільші таблиці — там зберігаються найважливіші дані. Перегляньте кілька рядків, щоб зрозуміти модель даних.
Крок 4: Визначте, що насправді ламається
Перевірте журнал помилок, який ви щойно увімкнули. У більшості застарілих сайтів є купа попереджень — не всі вони важливі. Пріоритет:
- Фатальні помилки — те, що ламає сторінки
- Застарілі виклики функцій — вони стають фатальними на PHP 8
- Помилки бази даних — невдалі запити, проблеми з підключенням
# Підрахувати типи помилок у журналі
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
Крок 5: Перед змінами створіть запобіжник
У застарілому коді немає тестів. Це означає, що будь-яка зміна може зламати те, чого ви не очікували.
Мінімальний запобіжник:
- Складіть список найважливіших сторінок/потоків (головна, вхід, оформлення замовлення, ключові форми)
- Задокументуйте, як виглядає «робочий стан» для кожного (вручну, за потреби зі скріншотами)
- Після кожної зміни вручну перевірте, чи кожен ключовий потік все ще працює
Для чогось складнішого допоможе простий скрипт димового тесту:
// smoke_test.php — запускати після кожної зміни
$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}
";
}
Крок 6: Виправляйте в порядку впливу
Порядок пріоритетів для застарілого PHP-сайту:
- Безпека — SQL-ін'єкції, витік облікових даних, вразливості завантаження файлів. Не обговорюється.
- Фатальні помилки — те, що ламається. Виправте їх спочатку.
- Сумісність з PHP — якщо потрібне оновлення версії, запустіть phpcs, щоб отримати список усіх проблем
- Попередження про застаріле — систематично очищайте їх; вони стають фатальними на PHP 8
- Продуктивність — тільки після того, як попереднє стабільно
Поширені проблеми безпеки в застарілому PHP
// ВРАЗЛИВО — SQL-ін'єкція
$id = $_GET['id'];
$q = mysql_query("SELECT * FROM users WHERE id = $id");
// ВИПРАВЛЕНО — параметризований запит
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]);
// ВРАЗЛИВО — XSS
echo "Hello " . $_GET['name'];
// ВИПРАВЛЕНО
echo "Hello " . htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');
// ВРАЗЛИВО — обхід шляху до файлу
include $_GET['page'] . '.php';
// ВИПРАВЛЕНО — білий список дозволених сторінок
$allowed = ['home', 'about', 'contact'];
$page = in_array($_GET['page'], $allowed) ? $_GET['page'] : 'home';
include $page . '.php';
Рішення про переписування
Це питання виникає завжди. Моє емпіричне правило:
Виправляйте та підтримуйте, якщо:
- Сайт працює і йому просто потрібно пережити оновлення PHP
- Бізнес-логіка складна і добре перевірена роками роботи в продакшені
- Бюджет обмежений
Переписуйте, якщо:
- Вразливості безпеки є фундаментальними для архітектури (їх не можна залатати)
- Сайту потрібні нові функції, які неможливо додати акуратно
- Кодова база настільки заплутана, що кожне виправлення ламає дві інші речі
Більшість застарілих сайтів, які я бачу, варті підтримки, а не переписування. Оцінка переписування завжди в 3 рази вища, ніж очікує клієнт, і це займає 6 місяців замість 6 тижнів.
Що я беру за роботу з застарілим кодом
Аудит (зрозуміти кодову базу та створити пріоритетний список проблем): $100–200 залежно від обсягу.
Міграція PHP 7→8: $200–500 для типового сайту, більше для великих спеціалізованих платформ.
Постійний ретейнер на підтримку: $100–200/місяць для невеликих сайтів (виправляти проблеми в міру їх виникнення, моніторити помилки).
Якщо ви успадкували щось, що повинне продовжувати працювати, і не знаєте, з чого почати, опишіть вашу ситуацію, і я скажу, що має сенс.