Переезд на PHP7
В почте попросили описать переезд на ПХП7, с какими сложностями встретились, как они решались. Опишу, пока не забыл — я этим занимался почти в одиночку, так как задача не была приоритетной. Я считал, что мы сможем получить хороший прирост производительности, поэтому сам её и делал в свободное время.
Если кому интересно, загруженность серверов, где крутится ПХП, действительно упала, примерно в 1,5—1,7 раза.
Вообще говоря, у ПХП есть довольно детальные описания того, что может пойти не так при смене версий, достаточно заглянуть в раздел «Изменения, ломающие обратную совместимость» нужной версии. Там можно сразу прикинуть что придётся поменять в коде, если вы хорошо его знаете.
Ниже мой собственный опыт.
Сначала я составил список всех модулей ПХП, которые у нас используются — натурально выписал из зависимостей пакета нашего продукта в табличку в местной «вики». На тот момент не все модули поддерживали «семёрку», поэтому к табличке я иногда возвращался и вносил изменения, если они случались.
Когда в табличке без поддержки остался единственный модуль ctwig от шаблонизатора «Твиг», решил, что без него мы можем обойтись — к этому времени в интернете появились замеры скорости и «Твиг» без модуля под «семёркой» демонстрировал похожие результаты с «пятёркой» и модулем.
Дальше я проверил не используются ли у нас где-то новые зарезервированные слова. Так как их использование вызовает ошибку синтаксиса, то случаи использования легко ловятся скриптом наподобие этого:
find . -type f \( -name '*.php' -o -name '*.inc' \) -exec php -l {} \; |
fgrep -v 'No syntax errors'
У нас, к слову, было несколько таких мест — например, был объявлен класс с разными полезными штуками для обработки строк, который назывался String. Так больше нельзя — зарезервированное слово.
Посложнее с обработкой исключений — класс Exception перестал быть базовым и если требуется ловить все исключения, то в «семёрке» лучше всего перехватывать всё, что реализует интерфейс Throwable.
У нас необработанные кодом исключения ловятся и пишутся в логи, для этого в нескольких местах кода есть перехват всего подряд. Выглядело это примерно так:
try {
// … какой-то код
} catch (Exception $e) {
DI::log->get('exception')->error($e);
throw $e;
}
Из-за пространства имён такие места простым поиском найти непросто, но специализированные редакторы неплохо справляются.
Несложными регулярками поискал различные непрямые выражения, там теперь тоже есть разница, нашёл всего несколько штук и поправил.
Потом я как-то походя заметил «нотисы», связанные с модулем Memcached и оказалось, что этого модуля сменилось АПИ, а в документации об этом не слова, пришлось писать прокси-класс. Сейчас документация уже обновлена, прокси мы убрали и просто переписали затронутые места.
Далее в дело вступили тестеры и программисты — в основном были исправления, связанные с тем, что в «семёрки» некоторые вещи устарели, ничего сверх этого я не припомню.
В целом мне кажется, переход прошёл безболезненнее, чем можно было бы ожидать — всё-таки изменения сделаны значительные. Правда и обновились мы очень поздно — отчасти потому, что я внимательно читал списки изменений к каждой версии, следил когда мажорные проблемы сменятся минорными, отчасти от того, что требовалась ещё и поддержка со стороны всех используемых нами модулей.
Евгений, а вы именно на 7.0 перешли? Я недавно перевел сайты на 7.1, и самая бесячая ошибка — «A non-numeric value encountered in ...», когда пустая строка в математических выражениях (’’ + 1) не интерпретируется как 0, а вызывает ворнинг.
Да, на 7.0, в этом году начинаем переходить на 7.2. Пока с такой ошибкой не сталкивался, я стараюсь следить за тем, чтобы программировали так, как будто у нас язык со статической типизацией.