class Number {
private int|float $number;
public function setNumber(int|float $number): void {
$this->number = $number;
}
public function getNumber(): int|float {
return $this->number;
}
}
В одном из выпусков подкаста "Цинковый прод" мы мельком обсуждали, что нового будет в языке PHP8. После записи я решил написать статью, чтобы сформулировать свои мысли по положению PHP в современной разработке.
Давайте определимся в целом, какую нишу занимал/занимает язык, и куда он движется
Изначально язык позиционировался как простой инструмент, в котором из коробки есть всё необходимое для web.
С одной стороны, это действительно так: без дополнительных библиотек можно, например, вытащить из суперглобальной переменной $_POST параметры POST-запроса и вставить их в mysql с помощью встроенных функций, и это вроде как здорово.
Также очень важно, что модель "рожден, чтобы умереть" (например, в php-fpm) упрощала и упрощает разработку до безумия: не нужно знать, что такое локи, дедлоки, утечки памяти и т.д. Не надо писать await перед каждой строкой кода и т.д.
Скрипт начал работать над входящим HTTP-запросом, поработал в отдельном процессе, ни с кем не общаясь, и сдох, очистив все после себя. Очень просто программировать. Порог входа — около нуля.
Опять же, можно обойтись без роутинга: имя файла — это уже описание роутов.
С другой стороны, увы, есть нюансы. Веб не стал ждать и ушел далеко вперед.
Веб не стал ждать и ушел далеко вперед
Сейчас повсеместно распространены вебсокеты: они нужны для онлайн игр, чатов, оповещений в SPA-приложениях и т.д. Но вы просто не можете держать на php чат на 10000 человек: php-fpm worker обрабатывает только одно соединение за раз. Нельзя просто так взять и нагородить 10000 процессов ОС.
Есть, конечно, ReactPHP, Swoole, Amphp, но это по сути костыли, с помощью которых можно попытаться обойти ограничения PHP. Однако это не сам язык, а именно костыли. Кто поручится, что проект Swoole проживет еще лет 5? Много ли народу его изучила? Куча тимлидов предпочитает для вебсокетов использовать другой язык (Go или nodejs) или же вообще выбросить php полностью и написать ВЕСЬ проект на конкурирующей технологии.
Еще раз: разработчки на Go точно знают, что такое горутина, и горутина никуда не денется из языка. Разработчик под nodejs точно знает, что такое async/await и Promise. В деталях.
А знает ли средний PHP-шник что-нибудь про ReactPHP? Нет!
Далее, современный веб зачастую строится на микросервисах, которые активно общаются друг с другом. Часть API выгодно строить с постоянным соединением и асинхронным взаимодействием. Попробуйте организовать GRPC-сервер на голом php без 100500 костылей сбоку. Вас будет ждать разочарование.
Короче, писать микросервисы на PHP невыгодно.
Веб становится всё более хайлоадистым. Увы и ах, как ни ускоряй PHP, но под каждый HTTP-запрос выделяется отдельный процесс — это поведение прибито гвоздями. Даже если скрипт просто ждет ответа от БД или внешнего API, и ничего не делает — процесс продолжает существовать. Т.е. для io-bound задач PHP опять же подходит хуже, чем nodejs/golang/etc.
Простота
Простота языка немного подрассосалась. Нет, серьёзно, никто уже не пихает $_POST прямо в mysql_query. В вашем проекте с вероятностью 99% есть фреймворк, куча зависимостей из Composer, соблюдение принципов проектирования и т.д., роутинг, заданный в конфиге или аннотациях, а не в именах файлов. Т.е. встроенность веб-фич из коробки никак не играет роли. Spring boot (java) не намного сложнее: поставил пару аннотаций, и вот уже ты запустил своё веб приложение.
Итак, какая же ниша?
Ниша по сути — это админки со сложной бизнес-логикой (т.е. на Golang такое писать нецелесообразно) и не особо нагруженные сайты. Здесь PHP — лидер. Язык не переусложнен многопоточностью, колбек-хеллами, приятный синтаксис, куча разработчиков, опыта применения и т.д.
Да-да, приятный синтаксис. Есть все необходимое, но не перегружено лишними фичами. Есть типизация аргументов функций и свойств классов — и этого почти достаточно. Хотя это всё проверяется только в рантайме, но даже это сильно помогает в разработке, да и IDE сразу подсказывает, где косяк.
С точки зрения типов не хватает дженериков. Чтобы на входе в функцию сразу было видно, что это не просто сферическая Collection
в вакууме, а Collection<User>
, т.е. коллекция объектов класса "пользователь". Читабельность выросла бы в разы.
PHP 8
Вернемся к нашим баранам. PHP8. Первое, что с гордостью пишут во всех статьях — это JIT, который будет включен в новую версию.
JIT
Это технология позволяет компилировать части кода в машинный код во время исполнения. Т.е. сначала ваш скрипт запускается интерпретатором, но по мере сбора статистики использования, какие-то самые нагруженные части кода будут компилироваться в машинный код, что позволит сильно ускориться со временем.
Является ли это киллер-фичей? Как бы да, но… По-моему, не особо. Проблемы, описанные выше это никак не решает. И я не видел, чтобы PHP использовали или планировали использовать как числодробилку. C, C++, Rust все равно будут подходить лучше и работать в разы быстрее. Т.е. имхо ускорение которое мы увидели в PHP7.* по сравнению с PHP5 — уже и так крутое. PHP и так один из самых быстрых скриптовых языков, быстрее чем Ruby и Python. Я очень уважаю команду PHP и Дмитрия Стогова в частности, но по-моему титанические усилия по добавлению JIT в PHP не совсем оправданы для реальных php-приложений.
Если честно, я бы предпочел, чтобы вместо этого был сделан шаг в сторону асинхронных возможностей. Какие-нибудь аналоги Async/await и Promise.
Атрибуты
Что еще интересного в PHP8? Атрибуты.
Если по-простому, то аннотации в Symfony будут выглядеть не так
/**
* @Route("/blog")
*/
public function list()
{
// ...
}
а как-то так:
<<Route("/blog")>>
public function list()
{
// ...
}
В общем, решили не развивать докблоки, а сделать нормальный синтаксис. В общем-то здорово, что так сделали. Симпатичный сахарок. Мне нравится. Хотя с практической точки зрения опять же, нельзя сказать, что это прям решает насущные проблемы.
Union Types и mixed
Пример говорит сам за себя, можно перечислять типы через символ |
class Number {
private int|float $number;
public function setNumber(int|float $number): void {
$this->number = $number;
}
public function getNumber(): int|float {
return $this->number;
}
}
Раньше бы здесь просто не указали тип. Сейчас можно выкрутиться и указать.
Кстати, еще в PHP8 можно указать тип mixed в явном виде.
Являются ли все эти фишечки Big deal? Имхо не особо.
Weak maps
Weak maps — более тонкое управление очисткой памяти для сложных долгоиграющих скриптов. Прямо скажем, не каждому разработчику это может потребоваться
Остальное
Чуть больше консистентности в функциях, где-то немного сахара добавлено, пара функций для работ со строками. И в общем-то всё.
Подробности можете посмотреть, например, в этой статье.
По-моему, PHP7.4 выглядел более мажорным и фичастым.
Вывод
Всё, что написано в статье — сугубо субъективно. Подытожу:
PHP — отличный (лучший) язык для написания админок сайтов. С приятным синтаксисом, отличным тулингом и тьмой разработчиков.
Но для хайлоада, микросервисов и асинхронных штук — язык так себе. И PHP8 на мой взгляд больших практических проблем никак не решает. Поэтому то тут, то там по-прежнему будут присутствовать вставки на nodejs/go для асинхронных задач.
Мы обязательно обсудим это в следующих выпусках подкаста "Цинковый прод", поэтому не забудьте подписаться.