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 для асинхронных задач.
Мы обязательно обсудим это в следующих выпусках подкаста "Цинковый прод", поэтому не забудьте подписаться.
AlexLeonov
С интересом наблюдаю, как 20 лет хоронят PHP. Ну да ничего. Ruby пережили, дай бог, и очередной golang переживём.
И пионеров, путающих асинхронность с поддержкой потоков на уровне языка — тем более переживём. Не первый раз.
Здоровья вам и долгих лет!
P.S. А самого Стогова слабо на подкаст позвать? И в глаза ему сказать, что он фигню делает?
Revertis
Ну вам же сказали про самую нужную фитчу, которую PHP дать не может — поддержание постоянного соединения с вебсокетом, с браузером юзера.
mayorovp
А как же ReactPHP?
ollisso
Вот пример использования вебсокета на чистом пхп.
phppot.com/php/simple-php-chat-using-websocket
Первая ссылка в гугле — но вообще их тысячи.
Сам лично запускал вебчат на вебсокетах и чистом пхп лет 8 назад — работает до сих пор.
Ну и писал игру на вебсокетах и тп — всё работало. Проблем с вебсокетами небыло.
И это всё ещё на пхп 5.2.
Сейчас ещё проще стало.
Только фишка в том что вебсокет далеко не всегда нужен.
varanio Автор
По сути — это вручную сделанный ивент луп. Тут есть ряд проблем. Представьте, что иногда у вас проскакивают долгие запросы в базу. В этот момент система не будет ничего принимать и отправлять, будет ждать ответа. PDO не умееет неблокирующие вызовы. Даже если извернуться и как-то сделать (вроде бы для amphp сделали вручную клиент для mysql), это все выглядит как нагромождение костылей, а не first class citizen
mayorovp
Если честно, то нагромождением костылей выглядят как раз нативные модули вроде того же mysqli.
malaf
Согласшусь. К сожалению, ассинхронность в php ещё сырая, могу судить по опыту использования amphp в продакшене, и будет требовать неоправданно больших усилий в поддержке, так как текущие библиотеки страдают нестабильностью (amphp/mysql, amphp/artax) и постоянно находятся какие-то ошибки, которых в нативных решениях будет сильно меньше.
Не то чтобы что-то реализовать нельзя на php, вопрос, что ряд задач сильно дешевле сделать другим способом.
cjaushe4ka
mysqli умеет асинхрооную работу с бд
omlk2011
Прошу проверить вашу гипотезу в моем чате, правда нужно авторизоваться с оплатой в 1 бакс :), а потом можете делать выводы о невозможности PHP поддерживать сокеты.
omlk2011
И забыл оставить линк: my_game with support web-sockets
Буду рад еслси кто проведет нагрузочное тестирование.
omlk2011
Голосование на хабре нужно изменить, если кто то голосует против, то должен оставить пояснение, а так это — устранение неподходящих.
michael_vostrikov
Вы рассылаете спам на сотню читателей с рекламой своего платного продукта, да еще и просите бесплатно оказать вам услуги по тестированию. Почему вас удивляет, что это кому-то не нравится?
omlk2011
Я дал ответ про web-sockets, и что может ли PHP держать нагрузку, как я могу еще доказать то что написал в комментарии, не дав линк на работающий проект? А то что кто то видит только спам — не значит что я сказал что то не то и голосование идет за ответ, а не люблю или не люблю(нравиться или не нравиться).
michael_vostrikov
Вы и дав ссылку на работающий проект доказать не сможете. Потому что кто его знает, PHP у вас там на сервере работает или что-то еще. Доказать можно только предоставив исходники.
Вы можете придерживаться того, что вы сами придумали, только окружающие не виноваты в том, что вы придумали.
Не "кто-то видит только спам", а "вы сказали что-то не то, поэтому в вашем ответе есть только спам", потому что вопрос о веб-сокетах в PHP тем, что вы написали, доказать нельзя.
То есть что получается. Вы сказали, что кто-то должен заплатить вам деньги, хотя это вы хотите что-то доказать; кто-то должен сделать какие-то действия, которые ничего не докажут; прорекламировали свой платный проект, хотя согласие на получение рекламы здесь вам никто не давал; и без обоснований обвинили широкий круг людей в низких моральных качествах. Далее вы задали вопрос "что не так", а когда получили честный ответ, что это из-за рекламы и некорректной логики, продолжаете говорить "нет, это неправда, вы всё врете".
omlk2011
Вы ничего не сделали что бы опровергнуть или доказать что я "
обманщик", но уже сильно уверенно утверждаете и за всех посетителей отвечаете. А также зачем мне портить свою репутацию обманывая молодых людей?Во-вторых я не обязан вам предоставлять исходный код. Я хочу что бы молодые ребята не велись на всякие манипуляции в комментариях о PHP и не проверив самостоятельно или посмотрев на проект(мой или чужой) сделали выводы, а также получали опыт.
Каждый сам решает платить или нет, почему вас это волнует. Может кто то посчитает что оплатив вход в проект он сам посмотрит как он работает, проверит работу чата и т.д. И я указал что вход платный потому что бы предупредить и не тратить время на регистрацию если она не пустит в проект без оплаты.
michael_vostrikov
Где именно я сказал, что вы обманщик?
Где именно я вас просил предоставить исходный код?
Вы не обязаны его предоставлять, поэтому могли просто не пытаться что-то доказать или опровергнуть. По веб-интерфейсу сервиса доказать или опровергнуть его нельзя, это просто факт, следствие законов логики. Даже если у вас там действительно работает PHP.
"Посмотреть на проект" означает "посмотреть на исходники". Чьи-то слова "да там точно одно соединение, правда-правда" ничего не доказывают. Может вы просто думаете, что там одно соединение, а работает оно совсем по-другому.
Меня это не волнует. Вы спросили "почему минусы", я дал вам ответ. При этом сам я минус не ставил.
А кто-то посчитает, что молодые ребята не должны тратить деньги на проверку исходного утверждения, потому что его можно проверить совершенно бесплатно. Минусы это и предупреждение для других, что к вашему комментарию стоит относиться с осторожностью.
Давайте я подробнее объясню. Вы написали комментарий как опровержение утверждения про веб-сокеты в PHP. Он его не опровергает, минусами люди выразили свое несогласие с вашей логикой. Также он содержит излишне необоснованные требования для проверки этого утверждения. Минусами люди выразили несогласие и с этим, проверить утверждение можно бесплатно. А также вы пытались это доказать рекламой своего платного сервиса, что вообще-то запрещено правилами. Вот за все это в совокупности каждый человек поставил один минус, и таких людей было несколько.
А как вы представляете ответ на вопрос "за что минусы" на сайте, где у каждого пользователя свой аккаунт? Ну можете считать, что у меня написано не "Люди поставили минус за то-то", а "Я бы поставил минус за то-то". Принципиально это ничего не меняет. Просто я вам объяснил, а остальные не хотят. Потому что никто не обязан вам что-то объяснять. Какие выводы сделать из этой информации, решайте сами.
gto
Еще в «ушедшем далеко вебе» были убийцы Flash и Silverlight. Хоронителям пора задуматься над тем, что из себя представляет веб на самом деле.
Molokastiy
Несколько раз прочитал, но не понял. Флеш и сервелат разве живые сейчас?
gto
Надеюсь, что нет. Просто их в своё время тоже называли убийцами хтмл. Говорили, что хтмл не тянет растущих потребностей пользователей, ну и всё такое прочее.
sanerrus
Хороший комментарий на мой взгляд, добавлю немного своего:
Главная проблема PHP на мой взгляд, это почти нулевая стоимость входа, люди нахватаются, он им все прощает, делают ошибки и считают что в этом проблема языка, а не их и кидаются изучать другой язык.
Вторая проблема PHP — люди не хотят глубоко вникать в него, например недавно столкнулся с человеком который считает что yild есть в phyton и нет в php. А вы знаете, что генераторы появились еще в PHP5.5? Вот статья интересная — nikic.github.io/2012/12/22/Cooperative-multitasking-using-coroutines-in-PHP.html
innovaIT
Я так думаю про golang. Он реально прощает многое. Точнее не даёт сделать себе выстрел в ногу. Для справки я занимаюсь 1с. Занимаюсь давно. И вот каждые года 3-4 я пробовал php. Что в первый раз он мне не зашёл ни по синтаксису, ни по парадигме. Когда я взял го, то понял, это тот язык, который мне нравится. Кроме нескольких исключений. Он простой, он лаконичен, он многопоточный, он ограждает меня от многих неприятностей на этапе компилирования. И самое главное синтаксис. Два дня мучений, и я начал такое использовать даже в 1с. Но он не позволяет одной переменной стать сначало строкой, а потом массивом. А 1С и php запросто. Он не позволяет ошибок проектирования.
Vilaine
Забавно регулярно оду типизации Go читать. Видимо, всё от разработчиков, всю жизнь писавших на динамических ЯП. Попробуйте Rust. Или хотя бы Typescript. Go слишком примитивен для каких-то там гарантий компиляции. И он нарочно примитивен.
Можете даже попробовать PHP + Psalm со всеми ошибками.
innovaIT
Поясните подробней? На раст давно смотрю, руки не доходят. Из разряда сам не пробовал но осуждаю. Вижу примеры кода, и синтаксис ужасный по мне. Похоже он ближе к низким ЯП. Таким как c++. А мне не очень хочется заниматься выделением/освобождением памяти. И прочими весёлыми операциями.
Vilaine
В принципе да, немало низкого уровня у этого улучшенного С, в отличие от Haskell. Там вообще думаешь только о задаче, но в менее привычных условиях.
В Go ведь очень распространено приведение типов из-за невыразительности системы типов, она же там почти как в Pascal. По сути всё есть явно и однозначно типизированные переменные и структуры. И под капотом больше, чем даёт синтакис.
В Rust есть например параметризация типов, тип-сумма, перечисления, абстрактные типы.
VanquisherWinbringer
Ну так для справки — по статистике из SO среди профессиональных разработчиков по сравнению с 2019 годом PHP, Ruby, Scala упали а Go, Kotlin, C# выросли. Просто цифры. insights.stackoverflow.com/survey/2020
chapuza
« Профессиональные разработчики» здесь — это на 95% люди, которые спрашивают, как развернуть связный список. Да и массовость и качество — очень слабо пересекающиеся характеристики.