О насБлогКонтакты
Backend18 февраля 2016 г. 4 мин 29

Как перейти с PHP 5.6 на PHP 7.0 без поломки приложения (2016)

AunimedaAunimeda
📋 Содержание

Как перейти с PHP 5.6 на PHP 7.0 без поломки приложения (2016)

Коротко: Запустите PHP 7 Migration Checker (php7cc или php_compat_check) — покажет несовместимый код. Главное: замените все mysql_* на PDO или mysqli_*, замените ereg() на preg_match(), удалите split(), проверьте конструкторы классов (PHP 4-style конструкторы устарели). Тестируйте на staging с PHP 7 перед деплоем.


Что изменилось в PHP 7.0 (Breaking Changes)

УДАЛЕНО (вызывает Fatal Error):
- mysql_*    функции (mysql_connect, mysql_query и т.д.)
- ereg(), eregi(), ereg_replace() — регулярные выражения POSIX
- split() — разделение строк
- mcrypt_* функции (deprecated в 7.1, removed в 7.2)
- dl() в многопоточных SAPI

ИЗМЕНИЛОСЬ:
- set_error_handler() теперь получает Fatal ошибки
- Операция деления на ноль: Warning вместо Fatal (PHP 7.0+)
- list() больше не принимает пустые элементы
- foreach не изменяет значение переменной итерации внутри цикла
- Конструкторы PHP 4-style (имя = имя класса) Deprecated

Шаг 1: Автоматическое обнаружение проблем

# Установить php7cc (PHP 7 Compatibility Checker)
composer global require sstalle/php7cc

# Сканировать весь проект
php7cc /var/www/myproject/

# Пример вывода:
# /var/www/myproject/lib/Database.php
#   Line 15: mysql_connect() is removed in PHP 7.0
#   Line 23: mysql_select_db() is removed in PHP 7.0
# /var/www/myproject/controllers/Search.php
#   Line 8: ereg() is removed in PHP 7.0

Шаг 2: Замена mysql_* на PDO

<?php
// СТАРЫЙ КОД (PHP 5.x) — не работает в PHP 7:
$conn = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('mydb', $conn);
mysql_query("SET NAMES 'utf8'");
$result = mysql_query("SELECT * FROM users WHERE id=" . $_GET['id']);
$row = mysql_fetch_assoc($result);

// НОВЫЙ КОД (PDO — работает в PHP 5.1+ и PHP 7+):
$pdo = new PDO(
    'mysql:host=localhost;dbname=mydb;charset=utf8mb4',
    'user', 'pass',
    [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);

// ОБЯЗАТЕЛЬНО: prepared statements (защита от SQL-инъекций)
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);

// Или с именованными параметрами:
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email AND status = :status");
$stmt->execute([':email' => $email, ':status' => 'active']);

Шаг 3: Замена ereg* на preg_*

<?php
// СТАРЫЙ КОД:
if (ereg('^[0-9]+$', $value)) { ... }
$cleaned = ereg_replace('[^a-zA-Z]', '', $input);

// НОВЫЙ КОД (preg_* работает и в PHP 5.x и PHP 7+):
if (preg_match('/^[0-9]+$/', $value)) { ... }
$cleaned = preg_replace('/[^a-zA-Z]/', '', $input);

// split() → explode() или preg_split()
// СТАРЫЙ:
$parts = split(',', $string);
// НОВЫЙ:
$parts = explode(',', $string);         // Для фиксированных разделителей
$parts = preg_split('/[,;]/', $string); // Для паттернов

Шаг 4: Конструкторы PHP 4-style

<?php
// СТАРЫЙ КОД (PHP 4-style — Deprecated в PHP 7):
class Database {
    function Database() {  // Имя метода = имя класса = конструктор
        $this->connect();
    }
}

// НОВЫЙ КОД:
class Database {
    function __construct() {  // Стандартный конструктор
        $this->connect();
    }
}

Шаг 5: Настройка PHP-FPM на Ubuntu

# Установить PHP 7.0 рядом с PHP 5.6
sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt-get install php7.0-fpm php7.0-mysql php7.0-mbstring php7.0-gd php7.0-xml php7.0-curl

# Проверить
php7.0 --version  # PHP 7.0.x

# Переключить nginx с PHP 5.6 на PHP 7.0
# В nginx конфиге: fastcgi_pass unix:/run/php/php5.6-fpm.sock
#                → fastcgi_pass unix:/run/php/php7.0-fpm.sock

Стратегия миграции без простоя

# 1. Staging: установить PHP 7.0, запустить приложение, исправить ошибки
# 2. Production: установить PHP 7.0 рядом с PHP 5.6
# 3. Создать тестовый поддомен: test.mysite.kg → PHP 7.0
# 4. Провести smoke-testing 24 часа
# 5. Переключить nginx:

# nginx конфиг:
# upstream php56 { server unix:/run/php/php5.6-fpm.sock; }
# upstream php70 { server unix:/run/php/php7.0-fpm.sock; }

# Переключение одной строкой:
# fastcgi_pass php56;  →  fastcgi_pass php70;

sudo nginx -t && sudo service nginx reload

# Откат за секунды (если что-то пошло не так):
# fastcgi_pass php70;  →  fastcgi_pass php56;

Новые возможности PHP 7 (стоит использовать)

<?php
// Декларация типов (Type Declarations) — PHP 7.0
function divide(int $a, int $b): float {
    if ($b === 0) throw new InvalidArgumentException('Division by zero');
    return $a / $b;
}

// Null coalescing operator — PHP 7.0
// Было:
$name = isset($_GET['name']) ? $_GET['name'] : 'default';
// Стало:
$name = $_GET['name'] ?? 'default';

// Spaceship operator — сравнение трёх значений
$result = $a <=> $b;  // -1 если a < b, 0 если равны, 1 если a > b

// Анонимные классы — PHP 7.0
$obj = new class(42) {
    public function __construct(private int $value) {}
    public function getValue(): int { return $this->value; }
};

Результаты после миграции

На нашем проекте (Laravel 5.2, 150k запросов/день):

Метрика PHP 5.6 PHP 7.0
Запросов/секунду 420 890
Память на процесс 45 МБ 28 МБ
Время ответа API (avg) 380 мс 190 мс
PHP-FPM воркеры 40 40 (обслуживают в 2x больше трафика)

Производительность удвоилась без изменения кода приложения. Для нагруженных систем это был бесплатный апгрейд.

Читайте также

REST API на PHP: уроки первого мобильного бэкендаaunimeda
Backend

REST API на PHP: уроки первого мобильного бэкенда

Мы писали первый REST API для iOS-приложения в 2013 году. Что такое настоящий REST, почему HTTP-методы важны, как сделать аутентификацию без сессий - и ошибки, которые мы совершили.

Оптимизация MySQL: переход с MyISAM на InnoDB и кэширование через Memcachedaunimeda
Backend

Оптимизация MySQL: переход с MyISAM на InnoDB и кэширование через Memcached

Как мы спасли продакшен-базу от деградации под нагрузкой: миграция с MyISAM на InnoDB, настройка пула буферов и внедрение Memcached - реальный кейс 2011 года.

PostgreSQL на VPS: от 10 до 1000 запросов в секунду без смены железаaunimeda
Backend

PostgreSQL на VPS: от 10 до 1000 запросов в секунду без смены железа

Практическое руководство по настройке PostgreSQL на VPS с 4 CPU и 8 ГБ RAM: правильные параметры postgresql.conf с расчётами, частичные и covering индексы, настройка autovacuum, PgBouncer для connection pooling. Реальные цифры: 23 мс → 1.2 мс на запрос.

Нужна IT-разработка для вашего бизнеса?

Разрабатываем сайты, мобильные приложения и AI-решения для бизнеса в Кыргызстане. Бесплатная консультация.

Получить консультацию Все статьи