286.15
Rating
Badoo
Big Dating

Вышел PHP 7.4! Как Badoo переходит на новую версию

Badoo corporate blogHigh performanceWebsite developmentPHPProgramming
Сегодня, наконец, опубликован релиз PHP 7.4!


Его новые фичи уже были многократно описаны, в том числе и на Хабре. Это стрелочные функции, типизированные свойства классов и ещё много всякого синтаксического сахара. Но больше всего мы ждали новый релиз из-за производительности: в версии 7.4 не только появился preload, но и сам PHP стал значительно быстрее.

Плохая (или хорошая?) новость — с выходом PHP 7.4 прекращается активная поддержка PHP 7.2. Его последний релиз запланирован на середину декабря. Мы давно проводим эксперименты с PHP 7.4, а недавно активно занялись переходом на него, так как сейчас мы на уже почти не поддерживаемой версии 7.2.

Поздравляю всех с долгожданным релизом! А ниже расскажу немного о том, как мы переходим на новую версию.

Несмотря на то, что у нас огромная кодовая база, мы живём на PHP уже 13 лет. Нам неоднократно приходилось переходить на новые версии, и процесс перехода хорошо отработан. 

Если сильно упростить, то можно выделить несколько шагов:

  • Добиваемся того, что unit-тесты начинают успешно проходить на новой версии.
  • Делаем обязательными прогоны тестов на новой версии для всех изменений кода (чтобы не пришлось повторять пункт 1, так как новый код пишется постоянно, и он может быть снова несовместимым).
  • Переключаем на новую версию девел-площадку, чиним проблемы и живём какое-то время в таком состоянии.
  • Повторяем это для стейджинга.
  • Плавно выкладываем на разные кластеры продакшена.

Наши правки в репозитории PHP


Проблема с preload (фикс)


В этот раз в процессе кое-что изменилось: так как мы очень ждали preload, начали проводить часть работы еще в июле, во время версии 7.4.0beta1. В итоге это вылилось для нас в достаточно большое количество времени, потраченного на отладку, ведь PHP 7.4 тогда был совсем сырым. Но с другой стороны, в результате мы нашли неприятный баг, починили его и отправили фикс в апстрим, чем помогли всему сообществу.

Дальше настало время заняться тестами.

Проблема с доступом к приватным свойствам (фикс)


Для того, чтобы вообще прогнать тесты, нужно обновить PHPUnit, SoftMocks и PHP-Parser как их часть. У нас большая кодовая база, и даже для обновления PHPUnit потребовалось переписать огромное количество тестов.

После того, как нам удалось прогнать тесты, мы увидели очень странное. Было много падений со следующей ошибкой:

PHP Fatal error: Cannot access private property ClassLoader::$classMap in vendor/composer/ClassLoader.php

Доступ к приватному свойству класса осуществляется только внутри него, но PHP рапортует об ошибке: нельзя получить доступ к приватному свойству, будто бы вызов происходит из другого класса.

Проблема осложнялась тем, что воспроизводилась нестабильно. Долгий дебаг при помощи gdb показал, что действительно в EG(fake_scope) по каким-то причинам оказывается не тот класс, в рамках которого происходит обращение к свойству, а другой, не связанный с ним.

После того, как мы нашли минимальный репродьюс-кейс (который, на минуточку, требует наличия трёх классов, автолоадера и Reflection), починили причину проблемы и запушили исправление в апстрим, оказалось, что эта проблема существовала ещё со времён PHP 7.3 (скорее всего, после вот этого изменения), весь мир жил с ней год и никому до нас она не мешала.

Правим несовместимости кода Badoo


Сейчас мы правим все несовместимости нашего кода с PHP 7.4. Подавляющее большинство несовместимостей для нас (больше сотни мест, >80% от всех несовместимостей) было вызвано добавлением ошибки «Trying to access array offset on value of type null/bool/int» (соответствующий RFC). Она возникает при использовании синтаксиса обращения к элементу массива на других типах данных. 

Проблему хорошо показывает вот такой пример:

$a = false;
var_dump($a[‘somekey’]);

// PHP 7.3: 
// NULL
// 
// PHP 7.4:
// Notice: Trying to access array offset on value of type bool in Command line code on line 1
// NULL

Навскидку кажется, что такого в реальном коде не должно встречаться, но, как показала практика, это достаточно частый случай: например, функция может возвращать массив в нормальном случае и false/null в случае ошибки, а дальше вверх по стеку информация о false/null теряется, и этот случай не обрабатывается отдельно. 

Это достаточно слабо распиаренное, но полезное изменение в PHP: оно позволяет найти много потенциальных ошибок в коде.

Второе по количеству доставленных проблем обновление — это изменение в работе method_exists(). Кстати, в настоящий момент информации о нём нет в release notes или upgrading guide. Суть его заключается в следующем:


class A1 { 
    private function priv() {} 
} 

class B1 extends A1 {} 

var_dump(method_exists(B1::class, 'priv'));

// PHP 7.3: bool(true)
// PHP 7.4: bool(false)

Эту особенность, опять же, сложно встретить в реальном коде. Но, как оказалось, мы ненамеренно активно эксплуатировали это в тестах.

Конечно, мы в разной степени сталкиваемся и с другими несовместимостями, в том числе с многочисленными изменениями, связанными с рефлексией (пример один, пример два), с изменениями в hexdec() и подобных, запретом array_key_exists() даже для ArrayAccess-объектов, с несовместимостями в различных библиотеках зависимостей, подключаемых через Composer, и даже со всякими экзотическими штуками вроде ставшим обязательным stream_set_option() для stream wrapper’ов при include’ах. Но в сумме затраты на адаптацию ко всем этим изменениям не сравнятся со случаем использования синтаксиса массивов на не-массивах.

В настоящий момент мы закончили работу с юнит-тестами: они полностью проходят на PHP 7.4. Ведём работу над API-тестами и до конца года планируем начать переключение различных кластеров и окружений.

Этой краткой заметкой хочу пригласить к обсуждению: пробовали ли вы уже PHP 7.4? Если да, то каким был ваш опыт? Собираетесь ли переходить?
Tags:phpphp 7.4
Hubs: Badoo corporate blog High performance Website development PHP Programming
+100
24.7k 59
Comments 27

Top of the last 24 hours

Information

Founded
2006
Location
Россия
Website
badoo.com
Employees
501–1,000 employees
Registered

Habr blog