Русский
Русский
English
Статистика
Реклама

Php8

Слабые места PHP думай как хакер

18.04.2021 12:07:38 | Автор: admin

Какие уязвимости можно найти в типичном PHP-проекте? Удивительно, но любые от слабых мест и уязвимостей в коде никто не застрахован. Чем быстрее мы их найдем, тем меньше риск для компании. Но чем лучше будем понимать, как можно атаковать наше приложение и как взаимодействуют друг с другом наши фичи, тем легче будет защитить код еще на уровне разработки. Тем более, что в PHP есть свои специфичные уязвимости те же type juggling, insecure deserialization и local file include.

Наиболее распространенные уязвимости из списка OWASP Top 10 (доля приложений)Наиболее распространенные уязвимости из списка OWASP Top 10 (доля приложений)

Чтобы повысить уровень безопасности кода, полезно думать как хакер и тестировщик одновременно, проверяя все возможные лазейки в коде. Сканеры уязвимостей, SSL-сертификаты, аудиты и прочие многочисленные инструменты защиты будут хорошим дополнением. О том, как всё это совместить, Антон Прохоров рассказал в нашем интервью. На конференции PHP Russia 2021 Антон представит в докладе уязвимости PHP-приложений и способы их эксплуатации.

Антон, как ты вообще попал в такую интересную сферу, как безопасность?

Еще в МИФИ на факультете информационной безопасности я увлекся практическими кейсами, а на старших курсах мы с однокурсниками стали бывать на профильных конференциях (Positive Hack Days, ZeroNights). А потом увидели финал соревнований CTF по практической информационной безопасности, заинтересовались и тоже создали команду для участия.

Как ты встретился с PHP? И чем занимаешься сейчас?

С PHP была связана моя первая работа я разрабатывал модули для сайта на Drupal. Но безопасность не завязана на один язык программирования, поэтому и на соревнованиях они были совершенно разные так что я никогда не был привязан ни к PHP, ни к другому конкретному языку. Участие в соревнованиях в итоге так меня увлекло, что я захотел работать в кибербезопасности и так пришел в BI.ZONE.

Что именно ты делаешь в BI.ZONE? Как участвуешь в анализе?

BI.ZONE предлагает много разных услуг: анализ защищенности приложений, инфраструктуры, реагирование на инциденты безопасности, и еще множество всего. Я занимаюсь поиском уязвимостей в приложениях заказчиков, а также участвую в тестированиях на проникновение. В случае с приложениями, нам предоставляют доступ, исходный код, какие-то тестовые стенды, учетные записи. Мы всё это смотрим, стараясь обеспечить полное покрытие всех функций, и в конце выдаем отчет: какие уязвимости нашли, и как можно их исправить. При тестировании на проникновение заказчик дает нам большой список внешних ресурсов компании, мы анализируем их, пытаемся найти уязвимости и с помощью них проникнуть во внутреннюю сеть компании. В таких проектах мы не стараемся полностью все проверить, а ищем самые уязвимые сервисы и используем баги в них.

И ты, помимо PHP, для каждого нового проекта изучаешь новый язык?

Приходится. Конечно, не на том уровне, на котором его знают разработчики, но какие-то базовые штуки надо знать, чтобы просто понимать где что находится в коде. То есть, когда я вижу HTTP-запрос на сайте, я должен примерно представлять, где найти код, который обрабатывает этот запрос. Такие вещи нужно знать, как и какие-то уязвимые конструкции в каждом языке. Приходится, конечно, достаточно часто менять стек сегодня ты с PHP разбираешься, завтра с .NET, послезавтра с Java, и т.д.

Насколько больше или меньше уязвимостей у PHP по сравнению с другими языками? Какие они?

Если говорить про интерпретатор языка и стандартные библиотеки, то так как они написаны на C, то в их коде часто обнаруживаются баги, связанные с управлением памятью и различными переполнениями, которые иногда могут приводить к уязвимостям. Больше их или меньше чем в интерпретаторах других языков я не возьмусь сравнивать. Из примеров можно вспомнить уязвимость PHP-FPM и unserialize. Но это довольно редкие и специфичные случаи.

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

Например?

Например, до 8 версии PHP, если при обращении к любому файлу использовать схему "phar://", интерпретатор будет воспринимать содержимое файла как Phar-архив: попытается найти в нем метаданные и десериализовать их. Если ваше приложение принимает от пользователей путь до файла и не проверяет схему, то это может в некоторых случаях привести к возможности исполнения произвольного кода на вашем сервере. Про такие нюансы я и хочу рассказать на конференции, показав примеры.

Если в PHP таких нюансов много, можно ли сказать, что он в целом более уязвим, чем другие языки?

Возможно, из-за того, что PHP в целом популярный язык, создается впечатление, что в приложениях, написанных на нем, уязвимостей больше. Но это, отчасти, обусловлено статистически: по различным данным около 50% сайтов из топ миллион используют PHP, никакой другой язык по этим показателям с ним не сравнится.

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

По твоему опыту, насколько PHP-разработчики заботятся о безопасности?

Я читаю, по большей части, только тот код, который нам предоставляют заказчики. И они уже, в основном, что-то знают о безопасности, раз хотят, чтобы их проверили. Но в целом мне кажется, что тенденция на более безопасный код. Если раньше еще можно было найти простейшую SQL-инъекцию, то сейчас это уже гораздо реже происходит, обычно обнаруживаются более сложные баги и цепочки уязвимостей.

Доли сайтов с уязвимостями различной степени риска по версии OWASPДоли сайтов с уязвимостями различной степени риска по версии OWASP

Пример цепочки можешь привести?

Например, приложение позволяет делать скриншоты веб-страниц: мы отправляем адрес страницы и в результате получаем картинку. Но при этом на сервере проверяется, что переданный нами адрес имеет домен example.com. А теперь, предположим, что мы нашли на сайте example.com уязвимость Open Redirect, позволяющую сформировать ссылку с доменом example.com, которая при открытии будет перенаправляться на произвольный адрес, например, localhost. И вот у нас уже есть возможность делать скриншоты страниц с localhost.

Что-то еще может помочь коду быть безопасным, кроме самообразования программистов?

Здесь, наверное, ничего нового не скажу. Нужно, чтобы заказчики и разработчики заботились о безопасности еще на этапе проектирования приложения, чтобы тестирование безопасности было включено в жизненный цикл разработки ПО. Проверки безопасности нужно внедрять в процесс разработки новых фич, чтобы не было так, что разработали все приложение, а после этого провели только аудит. Безопасность это все-таки процесс. Поэтому тестирование нужно проводить чаще и как можно раньше.

То есть и после того, как сдали проект, нужно время от времени проводить тестирование?

Да, можно добавить одну фичу и проверить ее уязвимостей нет. Добавить другую, и там их нет. Но, возможно, комбинация этих фич может привнести какую-то уязвимость. Проверки там, где это возможно нужно автоматизировать, добавлять в CI/CD сканеры уязвимостей и т.п. И конечно, обучать разработчиков, рассказывать, как писать безопасный код. Все это в совокупности, я думаю, приведет к тому, что приложение будет безопаснее. Но это не я придумал, это известная вещь Security Software Development Lifecycle.

Можно ли полностью автоматизировать проверки по безопасности?

Какие-то вещи да, но не полностью и не всё. Мы, конечно, используем сканеры кода и подобные утилиты, но они несовершенны. Во-первых, у них очень много ложных срабатываний, как false positive, так и false negative то есть они могут и найти то, что не является уязвимостью, и не найти какую-то уязвимость. Поэтому мы всегда проверяем его результаты насколько это вообще уязвимость, и если уязвимость, то можно ли ее эксплуатировать.

А во-вторых, некоторые категории уязвимостей сканеры вообще не находят, и пока нет даже предпосылок, что это когда-нибудь произойдет. Это уязвимости, связанные с конкретной бизнес-логикой приложения. Например, в интернет-магазине есть процесс пользователь кладет в корзину товар и оплачивает его. Только здесь может быть уже множество уязвимостей, которые не являются типовыми, вроде SQL-инъекций или XSS-атак. Это может быть, например, связано с передачей отрицательной суммы или неправильной обработкой скидок и т.п. Такое сканер пока что не может обнаружить, потому что здесь нужно знать контекст: что это за приложение и какие там могут быть угрозы. Таких вариантов может быть много и в других процессах так что нам всегда найдется, что делать.

То есть когда ты читаешь код, то проверяешь также все возможные варианты развития по какому-то процессу?

Во-первых, я пользуюсь уже готовыми методологиями, вроде OWASP. Во-вторых, какие-то типовые атаки я уже знаю из опыта. Плюс я интересуюсь тем, что другие находят так складывается мой справочник Что еще можно проверить? Да и в общем, да я пытаюсь думать как злоумышленник.

Если мы нашли уязвимость и хотим сообщить об этом, как заказчику наладить работу с такими сторонними исследователями безопасности?

В первую очередь, нужно на видное место на сайте добавить контакты или форму для связи: чтобы человек мог обратиться по поводу уязвимости, и чтобы это можно было легко найти. Чтобы не приходилось писать на какой-нибудь ящик компании support@ или sales@ и пытаться связаться с разработчиками или безопасниками это бывает и сложно, и долго.

А второе, если уже компания довольно большая и действительно думает о том, как сделать так, чтобы её продукты постоянно тестировали можно использовать Bug Bounty платформы, те же Hackerone и Bugcrowd. Суть в том, что компания договаривается с платформой, оговаривает скоуп ресурсов, которые будут исследоваться, принимаемые уязвимости и вознаграждение за них. В Bug Bounty участвуют уже много российских компаний Киви, Майл.ру, Яндекс. Можно посмотреть на их примере.

Что не стоит делать в таких случаях при работе со сторонними исследователями?

Я думаю, если вам написали, что у вас уязвимость, не стоит игнорировать такое сообщение. Лучше разобраться в проблеме и ответить.

А правда ли, по твоему опыту, что простые уязвимости самые страшные, а сложные никому особо не нужны?

Думаю, это не так, потому что обычно уязвимости оцениваются по тому, что с их помощью можно сделать. Например, с помощью уязвимости мы можем прочитать данные любого пользователя или получить исполнение команд на сервере и т.п. Чем больше потенциальный ущерб, который может принести эксплуатация уязвимости, тем она и ценнее, за нее больше заплатят на Bug Bounty. А уж сложная она или простая это другое дело. Но, конечно, если она простая, то, возможно, больше людей ее могут найти. И она этим страшнее. Может быть, пока ее обрабатывали на платформе Bug Bounty, уже кто-то из злоумышленников научился ее эксплуатировать. Но в целом, я думаю, что важен именно ущерб от уязвимости, а не простота или сложность.

То есть если большой ущерб ожидается от сложной уязвимости, ее все равно могут использовать?

Да, конечно. Из последнего здесь можно привести в пример довольно сложную цепочку уязвимостей в Microsoft Exchange под названием Proxylogon, которая, как известно, эксплуатировалась злоумышленниками.

А много ли тех, кто может самостоятельно найти новую уязвимость без использования готовых наборов или сканеров?

Если имеется в виду новая уязвимость как класс, то, наверное, единицы. Мы обычно изучаем уже известные классы уязвимостей и применяем эти знания для анализа приложений заказчика. Если же под новой уязвимостью подразумевается просто уязвимость в каком-либо приложении, которую еще не находили, то в целом это как раз то, чем занимаются люди моей профессии.

Какие уязвимости, найденные за твою практику, запомнились тебе больше всего?

Наверное, здесь стоит упомянуть уязвимость, из-за которой я попал на PHP Russia. Я нашел цепочку гаджетов для десериализации в PHP, которая позволяет исполнять код, используя только классы фреймворка Yii2. Это в общем-то проблема не самого фреймворка, а приложения, которое его использует. Но если программисты в приложении десериализуют пользовательские данные, то используя только классы фреймворка, можно получить исполнение команд на их сервере.

Хоть это и не сильно относится к самому фреймворку, я все равно написал разработчикам. Меня порадовало, что откликнулись и исправили. Я как раз общался с Александром Макаровым, как одним из разработчиков фреймворка, и после того общения он пригласил меня выступить на конференции.

На конференции ты собираешься рассказывать как раз о безопасности в коде. Можешь рассказать об этом подробней?

Я расскажу о нюансах PHP, которые стоит учитывать, если мы хотим писать безопасный код. Это специфичные уязвимости конкретно для PHP, не для других языков. Например, в PHP нестрогая типизация, поэтому строки приводятся к числам, числа к строкам, и т.п. Это может вести к разным интересным уязвимостям при сравнении, так как иногда приведение типов происходит не самым очевидным образом. Расскажу и про другие классы уязвимостей, которые есть в PHP. Покажу на примере, как это эксплуатировать, чтобы разработчики знали, что такая конструкция уязвима, и не стоит так писать.

А сам ты впервые выступаешь на конференциях, иди у тебя уже есть опыт? Тебе нравится?

Я выступал, но не очень много. Это довольно волнительно для меня. Но зато приходится более глубоко разбираться в теме, чтобы быть готовым к разным вопросам. Получается, что когда готовишься к выступлению, сам много всего нового узнаешь.

И сам доклад получается по-настоящему классный.

Надеюсь, это будет полезно тем, кто прослушает доклад.

PHP Russia 2021 пройдёт в гибридном формате будет и офлайн, и онлайн. Онлайн-зрители смогут задавать вопросы спикерам в зале, принимать участие в дискуссиях и участвовать в активностях на стендах партнёров.

Мы с нетерпением ждём нашу встречу в офлайне 28 июня 2021 года. До 30 апреля стоимость очного участия составит 27 000 рублей

Подписывайтесь на наши соцсети, чтобы быть в курсе новостей (FB,VK,Telegram-канал,Twitter), общайтесь с коллегами в чате.

Подробнее..

Перевод Понимаем JIT в PHP 8

05.07.2020 04:21:30 | Автор: admin
Перевод статьи подготовлен в преддверии старта курса Backend-разработчик на PHP



TL;DR


Компилятор Just In Time в PHP 8 реализован как часть расширения Opcache и призван компилировать операционный код в инструкции процессора в рантайме.

Это означает, что с JIT некоторые операционные коды не должны интерпретироваться Zend VM, такие инструкции будут выполняться непосредственно как инструкции уровня процессора.

JIT в PHP 8


Одной из наиболее комментируемых фич PHP 8 является компилятор Just In Time (JIT). Он на слуху во множестве блогов и сообществ вокруг него много шума, но пока я нашел не очень много подробностей о работе JIT в деталях.

После многократных попыток и разочарований найти полезную информацию, я решил изучить исходный код PHP. Совмещая свои небольшие познания языка С и всю разбросанную информацию, которую я смог собрать до сих пор, я сумел подготовить эту статью и надеюсь, что она поможет вам лучше понять JIT PHP.

Упрощая вещи: когда JIT работает должным образом, ваш код не будет выполняться через Zend VM, вместо этого он будет выполняться непосредственно как набор инструкций уровня процессора.

В этом вся идея.

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

Я уже писал статью с кратким обзором того, как работает php. Если вам покажется, что эта статья становится чересчур сложной, просто прочитайте ее предшественницу и возвращайтесь. Это должно немного облегчить ситуацию.

Как выполняется PHP-код?


Мы все знаем, что php интерпретируемый язык. Но что это на самом деле означает?

Всякий раз, когда вы хотите выполнить код PHP, будь то фрагмент или целое веб-приложение, вам придется пройти через интерпретатор php. Наиболее часто используемые из них PHP FPM и интерпретатор CLI. Их работа очень проста: получить код php, интерпретировать его и выдать обратно результат.

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

  1. Код PHP читается и преобразуется в набор ключевых слов, известных как токены (Tokens). Этот процесс позволяет интерпретатору понять, в какой части программы написан каждый фрагмент кода. Этот первый шаг называется лексирование (Lexing) или токенизация (Tokenizing).
  2. Имея на руках токены, интерпретатор PHP проанализирует эту коллекцию токенов и постарается найти в них смысл. В результате абстрактное синтаксическое дерево (Abstract Syntax Tree AST) генерируется с помощью процесса, называемого синтаксическим анализом (parsing). AST представляет собой набор узлов, указывающих, какие операции должны быть выполнены. Например, echo 1 + 1 должно фактически означать вывести результат 1 + 1 или, более реалистично, вывести операцию, операция 1 + 1.
  3. Имея AST, например, гораздо проще понять операции и их приоритет. Преобразование этого дерева во что-то, что может быть выполнено, требует промежуточного представления (Intermediate Representation IR), которое в PHP мы называем операционный код (Opcode). Процесс преобразования AST в операционный код называется компиляцией.
  4. Теперь, когда у нас есть опкоды, происходит самое интересное: выполнение кода! PHP имеет движок под названием Zend VM, который способен получать список опкодов и выполнять их. После выполнения всех опкодов программа завершается.


Чтобы сделать это немного нагляднее, я составил диаграмму:


Упрощенная схема процесса интерпретации PHP.

Достаточно прямолинейно, как вы можете заметить. Но здесь есть и узкое место: какой смысл лексировать и парсить код каждый раз, когда вы его выполняете, если ваш php-код может даже не меняется так часто?

В конце концов, нас интересуют только опкоды, верно? Правильно! Вот зачем существует расширение Opcache.

Расширение Opcache


Расширение Opcache поставляется с PHP, и, как правило, нет особых причин его деактивировать. Если вы используете PHP, вам, вероятно, следует включить Opcache.

Что он делает, так это добавляет слой оперативного общего кэша для опкодов. Его задача состоит в том, чтобы извлекать опкоды, недавно сгенерированные из нашего AST, и кэшировать их, чтобы при дальнейших выполнениях можно было легко пропустить фазы лексирования и синтаксического анализа.

Вот схема того же процесса с учетом расширения Opcache:


Поток интерпретации PHP с Opcache. Если файл уже был проанализирован, php извлекает для него кэшированный операционный код, а не анализирует его заново.

Это просто завораживает, как красиво пропускаются шаги лексирования, синтаксического анализа и компиляции.
Примечание: именно здесь лучше всего себя проявляет функция предварительной загрузки PHP 7.4! Это позволяет вам сказать PHP FPM анализировать вашу кодовую базу, преобразовывать ее в опкоды и кэшировать их даже до того, как вы что-либо выполните.

Вы можете начать задумываться, а куда сюда можно прилепить JIT, верно?! По крайней мере я на это надеюсь, именно поэтому я и пишу эту статью

Что делает компилятор Just In Time?


Прослушав объяснение Зива в эпизоде подкастов PHP и JIT от PHP Internals News, мне удалось получить некоторое представление о том, что на самом деле должен делать JIT

Если Opcache позволяет быстрее получать операционный код, чтобы он мог переходить непосредственно к Zend VM, JIT предназначить заставить его работать вообще без Zend VM.

Zend VM это программа, написанная на C, которая действует как слой между операционным кодом и самим процессором. JIT генерирует скомпилированный код во время выполнения, поэтому php может пропустить Zend VM и перейти непосредственно к процессору. Теоретически мы должны выиграть в производительности от этого.

Поначалу это звучало странно, потому что для компиляции машинного кода вам нужно написать очень специфическую реализацию для каждого типа архитектуры. Но на самом деле это вполне реально.

Реализация JIT в PHP использует библиотеку DynASM (Dynamic Assembler), которая отображает набор команд ЦП в конкретном формате в код сборки для многих различных типов ЦП. Таким образом, компилятор Just In Time преобразует операционный код в машинный код для конкретной архитектуры, используя DynASM.

Хотя одна мысль все-таки не давала мне покоя

Если предварительная загрузка способна парсить php-код в операционный перед выполнением, а DynASM может компилировать операционный код в машинный (компиляция Just In Time), почему мы, черт возьми, не компилируем PHP сразу же на месте, используя Ahead of Time компиляцию?!

Одна из мыслей, на которые меня натолкнул эпизода подкаста, заключалась в том, что PHP слабо типизирован, то есть часто PHP не знает, какой тип имеет переменная, пока Zend VM не попытается выполнить определенный опкод.

Это можно понять, посмотрев на тип объединения zend_value, который имеет много указателей на различные представления типов для переменной. Всякий раз, когда виртуальная машина Zend пытается извлечь значение из zend_value, она использует макросы, подобные ZSTR_VAL, которые пытаются получить доступ к указателю строки из объединения значений.

Например, этот обработчик Zend VM должен обрабатывать выражение меньше или равно (<=). Посмотрите, как он разветвляется на множество различных путей кода, чтобы угадать типы операндов.

Дублирование такой логики вывода типов с помощью машинного кода неосуществимо и потенциально может сделать работу еще медленнее.

Финальная компиляция после того, как типы были оценены, также не является хорошим вариантом, потому что компиляция в машинный код является трудоемкой задачей ЦП. Так что компиляция ВСЕГО во время выполнения плохая идея.

Как ведет себя компилятор Just In Time?


Теперь мы знаем, что не можем вывести типы, чтобы генерировать достаточно хорошую опережающую компиляцию. Мы также знаем, что компиляция во время выполнения стоит дорого. Чем же может быть полезен JIT для PHP?

Чтобы сбалансировать это уравнение, JIT PHP пытается скомпилировать только несколько опкодов, которые, по его мнению, того стоят. Для этого он профилирует коды операций, выполняемые виртуальной машиной Zend, и проверяет, какие из них имеет смысл компилировать. (в зависимости от вашей конфигурации).

Когда определенный опкод компилируется, он затем делегирует выполнение этому скомпилированному коду вместо делегирования на Zend VM. Это выглядит как на диаграмме ниже:


Поток интерпретации PHP с JIT. Если они уже скомпилированы, опкоды не выполняются через Zend VM.

Таким образом, в расширении Opcache есть пара инструкций, определяющих, должен ли определенный операционный код быть скомпилирован или нет. Если да, то компилятор преобразует его в машинный код с помощью DynASM и выполняет этот новый сгенерированный машинный код.

Интересно, что, поскольку в текущей реализации есть ограничение в мегабайтах для скомпилированного кода (также настраиваемое), выполнение кода должно иметь возможность беспрепятственного переключения между JIT и интерпретируемым кодом.

Кстати, эта беседа Бенуа Жакемона о JIT от php ОЧЕНЬ помогла мне разобраться во всем этом.

Я до сих пор не уверен в том, в каких конкретных случаях происходит компиляция, но я думаю, что пока не очень хочу это знать.

Так что, вероятно, ваш прирост производительности не будет колоссальным


Я надеюсь, что сейчас гораздо понятнее, ПОЧЕМУ все говорят, что большинство приложений php не получат больших преимуществ в производительности от использования компилятора Just In Time. И почему рекомендация Зива для профилирования и эксперимента с различными конфигурациями JIT для вашего приложения лучший путь.

Скомпилированные опкоды обычно будут распределены между несколькими запросами, если вы используете PHP FPM, но это все равно не изменит правила игры.

Это потому, что JIT оптимизирует операции с процессором, а в настоящее время большинство php-приложений в большей степени завязаны на вводе/выводе, нежели на чем-либо еще. Не имеет значения, скомпилированы ли операции обработки, если вам все равно придется обращаться к диску или сети. Тайминги будут очень похожи.

Если только...

Вы делаете что-то не завязанное на ввод/вывод, например, обработку изображений или машинное обучение. Все, что не касается ввода/вывода, получит пользу от компилятора Just In Time. Это также причина, по которой люди сейчас говорят, что они склоняются больше к написанию нативных функций PHP, написанных на PHP, а не на C. Накладные расходы не будут разительно отличаться, если такие функции будут скомпилированы в любом случае.

Интересное время быть программистом PHP

Я надеюсь, что эта статья была полезна для вас, и вам удалось лучше разобраться, что такое JIT в PHP 8. Не стесняйтесь связываться со мной в твиттере, если вы хотите добавить что-то, что я мог забыть здесь, и не забудьте поделиться этим со своими коллегами-разработчиками, это, несомненно, добавит немного пользы вашим беседам!-- @nawarian



PHP: статические анализаторы кода


Подробнее..

29 ноября в Москве конференция по PHP в России будет офлайн

16.10.2020 14:10:19 | Автор: admin
Пандемия повлияла на все бизнес-процессы, мы долго были в онлайне. Но 29 ноября PHP-разработчики смогут наконец встретиться офлайн в тёплой атмосфере, увидеть лучших спикеров PHP-вселенной, и задав им вопросы, разобрать актуальные кейсы и обсудить проблемы. PHP Russia 2020 пройдёт в Москве в гостинице Radisson Slavyanskaya. Приходите, если хотите получить ускорение и направление в развитии плюс набраться новых идей для своих проектов!

Александр Макаров расскажет о предстоящих активностях на конференции, о некоторых интерактивах и других нюансах. Александр эксперт в PHP, лидер фреймворка Yii, соавтор Yii 2 и представитель Yii в PHP-FIG. Кроме разработки фреймворка успел поработать в разных компаниях, таких как Skyeng, Wrike и Stay.com и перепробовать в бою целые поколения разных технологий.

Мы расспросили Александра как главу программного комитета по PHP Russia 2020 обо всех активностях и интересностях встречи.



Саша, что нас ждет на первой в этом году оффлайновой конференции?
Будет много интересных докладов :)

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

Мы отобрали доклады, в которых раскроем разные способы писать код: микросервисы, параллельная обработка, долгоживущие процессы. Покажем, как ещё вы можете использовать PHP, а с чем не стоит связываться, и разберем, как лучше оформить решения распространенных практических проблем. Поговорим, как организовать системную работу с legacy и справиться с техдолгом. Покажем, как legacy-проекты продолжают развиваться без радикального переписывания кода.

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

Будет, естественно, информация про PHP 8, и затронем интересную тему: она не совсем по PHP, а про написание плагинов для нашей любимой IDE PhpStorm.

Как и в прошлые разы, неплохо представлены такие лидеры PHP-разработки, как BADOO, Skyeng, ManyChat, Onliner, Lamoda, Авито и SuperJob. Они работают не только на PHP, но PHP это самое главное в их стеке. Необязательно все выступят с докладами, но представители этих компаний будут все.

И конечно, будут представлены всякие интересные библиотеки, практики, подходы и подходы к тестированию, и интересные походы к разработке, и опыт больших компаний, который можно перенять. Расписание не совсем ещё сформировано, но уже есть предварительная сетка. Скорее всего, доклады ещё будут, будет больше и ещё интереснее.

Что необычного будет в этот раз?
Будет необычный формат с Дмитрием Стоговым из команды самого PHP. Он сделал JIT PHP.
Дмитрий приезжает не с докладом, а пообщаться в свободной форме с сообществом. Будет шанс задать ему любые вопросы не только про PHP 8 (и вообще про PHP), но и про остальную разработку, и даже чем он занимается в его свободное время. У Дмитрия неисчерпаемое множество тем для разговора, с ним очень интересно, а мы будем модерировать эту сессию вопросов и ответов.

Ещё в прошлый 2019-й офлайн мы попробовали такой замечательный формат как Unconference куда все желающие могли прийти и в блиц-формате рассказать про то, что они делают. Это тогда классно зашло, потому что были такие совершенно неожиданные рассказы, из которых потом получились и opensourse-бибилиотеки, и всякие крутые штуки. На онлайн-митапах, на которых мы сейчас иногда пересекаемся, до сих пор все с теплотой вспоминают эту встречу. Мы решили, что раз так, то этот формат забрасывать не надо, он классный. И мы повторим его в этом году.

Получается, в этом году будет сделан упор на общение, по которому все так соскучились?
Да. Мы решили доклады сделать немного разряженнее, а перерывы побольше. Это к тому же будет безопаснее в плане вирусов. Разумеется, по всем сегодняшним стандартам площадку мы обезопасим по максимуму, и это будет намного безопаснее, чем ездить в метро за счет дезинфекций, за счет проветривания, измерения температуры на входе, санитайзеров. Докладчик в маске будет вряд ли он стоит больше чем за полтора метра от первого ряда, но для остальных маски будут обязательными.

Что будет с конференцией и билетами, если введут карантин и мы все вынужденно останемся дома?
Сейчас мы исходим из того, что короновирус с нами надолго, мы делаем максимальные предосторожности и все-таки встречаемся, потому что жить как-то надо, новую информацию получать надо, и мы готовы её давать, даже несмотря на такие обстоятельства.
Но если вторая волна накроет нас совсем по полной, и запретят все-все-все мероприятия, билеты покупать на конференцию всё равно стоит.

Почему?
Потому что даже если произойдет закрытие всех конференций, у нас есть план Б. Билет никуда не девается, не сгорает, его можно использовать на следующий раз или на перенесенной конференции. То есть просто сдвинется дата, у нас есть об этом договоренности с площадкой и всеми подрядчиками.

То есть, если ничего не будет, то PHP-конференции не уйдет в онлайн?
Да. В прошлый раз она была онлайн, это было сильно, классно, но это показало, что онлайн это другая среда, совершенно другая штука. Классно то, что можно не привозя спикеров из очень дальних уголков, их всё-таки послушать. И просто и замечательно было в том, что в плане накладок ни мы, ни они ничего не теряли.

Но онлайн-формат намного сложнее в том плане, что всё получается нестабильно могут рваться соединения, что-то еще случаться, нужно озаботиться о том, чтобы звук хороший был у всех, чтобы камеры нормальные были и т.д. Это технически очень сложно. Плюс еще, получается, что люди из разных часовых поясов вещают, и у некоторых в это время уже ночь. Совсем без онлайна в ковидный период было бы плохо, но и слишком много онлайна тоже надоедает, и хочется всё-таки пообщаться вживую.

На обычной конференции доклады нужны не только для того, чтобы их послушать. Они классные, в них есть информация, которую ты выносишь для себя и проектов. Но главная цель конференции задать тему и обменяться опытом. Бывает, что, лично поговорив с другими участниками, ты получаешь и очень много заряда на будущее, и классную информацию, и возможно, даже решение своих текущих проблем, а ещё идеи и направления. От разговоров вне докладов мы получаем не меньше, чем от самого выступления.

В онлайне всего этого нет, и это большая потеря. То есть, возвращаясь к вопросу, даже если конференция закроется из-за вируса сейчас, она не отменяется, а просто переносится на более позднее время. И билеты не сгорают

Много в этом году желающих выступить? Спикеры соскучились по офлайн-формату?
Да, несмотря на все преграды, для офлайн-встречи была достаточно большая конкуренция. Даже пришлось отклонить действительно очень хорошие доклады, потому что они пересекались с теми, которые подходили по тематике больше. Вообще мы можем зарубить даже интересный доклад, если спикер не говорит ничего о применимости темы на практике это обязательный элемент.

Открой, пожалуйста, процесс, который начинается после выбора доклада.
Открываю. Каждый доклад после подачи закрепляется за кем-то из ПК. После этого мы смотрим черновой вариант доклада, даже без слайдов на первом этапе. И мы обязательно валидируем начальный вариант доклада: какие мысли хочется рассказать и т.д.

То есть мы обсуждаем всем программным комитетом и вместе принимаем решение брать это направление или нет, зайдет или нет, на чем лучше акцентировать внимание, а на чем не стоит, и т.д. По большому счету, это зависит от того, знакома тема всем или эта тема еще неизвестна многим. Так мы задаем спикеру путь, куда копать.

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

За счет прогонов и крутой экспертизы у ПК (они все очень опытные докладчики, которые выступали в том числе и в Европе), получаются очень качественные доклады на выходе, и мы стараемся не опускать планку.

Есть ли шанс, что не очень известный и не очень опытный разработчик найдёт тему, которая зайдет так же, как от более опытных коллег?
Да. Приведу пример.

В этом году мы спросили региональные PHP-сообщества, хотят ли они выступать и есть ли что у них для митапов (чтобы с ними созвонились с конференции и послушали, что у них там делается в компаниях, проектах, и так далее). Они начали присылать, и мы смотрели две вещи: годная ли информация для докладов в принципе и достаточно ли она крутая для конференции.

И результаты есть. Мы созванивались с ними 2-3 недели, всех послушали, и действительно есть классные и сильные ребята. Многие темы в этом году не подойдут, потому что они уже закрыты или авторами самих инструментов или кем-то супер-опытным. Но в общем очень достойно всё кое-кого мы включим в основную программу.

Когда мы вписывались в работу с ними, мы не надеялись, что сразу на конференцию кто-то попадет. Без подготовки обычно мало что есть, но мы были приятно удивлены, что подачи докладов состоялись. И даже если кто-то не подался, он теперь знает глобальное направление, и это хорошо для обмена информацией и активностями в сообществах. Сообщества будут расти, развиваться, выведут PHP вперед и придут к нам с новыми офигенными рассказами.

Пользуясь случаем, передаю привет и спасибо PHP-сообществам, которые нас поддерживают.

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

Must learn PHP Tools:


PHP Engineer Things to Learn:


На конференции PHP Russia 2020 Александр Макаров выступит с докладом Поговорим про код в рамках лучших практик PHP. Вы узнаете принципы, позволяющие писать код, который ломается меньше. Например, о композиции и как её форсировать. О private по умолчанию и именованных конструкторах. О состоянии и иммутабельности, а также о цепочке вызовов и многом другом.

29 ноября мы встретимся в ламповом инфопространстве, чтобы наконец увидеть друг друга вживую. Здесь можно забронировать билет на PHP Russia 2020. Подключайтесь к telegram-сообществу, чтобы обсудить архитектурные вызовы и любые другие вопросы по PHP.

Присоединяйтесь к нам на конференции, не только доклады будут полезны, но и профессиональное общение (настоящее, офлайновое!) даст энергию, чтобы воплощать услышанное. Мы с нетерпением ждём встречи в офлайне!
Подробнее..

Перевод PHP 8 пробуем новые возможности

29.10.2020 20:09:21 | Автор: admin

PHP 8 уже на этапе release candidate, версия RC 3 вышла 29 октября, а полноценный релиз назначен на 26 ноября. Так что пора взглянуть на новые возможности, которые нас ждут в PHP 8. График релизов можно посмотреть здесь. А официальное руководство по обновлению на новую версию лежит тут.

Добавлена поддержка типов union (RFC)


Тип union принимает значения разных других типов, а не только какого-то одного.

<?phpdeclare(strict_types=1); class Number {    private int|float $number;     public function setNumber(int|float $number): void {        $this->number = $number;    }     public function getNumber(): int|float {        return $this->number;    }} /** * We can pass both floats or integer values * to the number object. Try passing a string. */$number = new Number(); $number->setNumber(5); dump($number->getNumber()); $number->setNumber(11.54); dump($number->getNumber()); exit;

Добавлены WeakMap (RFC)


Слабые карты (weak maps) позволяют создавать связи между объектами и произвольными значениями (как и SplObjectStorage), при этом объекты, используемые в качестве ключей, не защищаются от сборщика мусора. Если сборщик уничтожает такой объект, тот просто удаляется из карты.

Это очень полезная фича. Она позволяет нам ещё меньше думать об утечках памяти в коде. Хотя для большинства PHP-разработчиков это не должно быть проблемой, но стоит обращать внимание при создании долгоиграющих процессов, например, используя ReactPHP. С WeakMaps ссылки на объекты автоматически собираются сборщиком мусора, когда объект становится недоступен.

Если вы сделаете то же самое с массивом, то ссылки на объект сохранятся, что приведёт к утечке памяти.

<?phpdeclare(strict_types=1); class FooBar {    public WeakMap $cache;        public function __construct() {      $this->cache = new WeakMap();    }     public function getSomethingWithCaching(object $obj) {        return $this->cache[$obj] ??= $this->computeSomethingExpensive($obj);    }        public function computeSomethingExpensive(object $obj) {    dump("I got called");    return rand(1, 100);    }} $cacheObject = new stdClass; $obj = new FooBar;// "I got called" only will be printed once$obj->getSomethingWithCaching($cacheObject);$obj->getSomethingWithCaching($cacheObject); dump(count($obj->cache)); // When unsetting our object, the WeakMap frees up memoryunset($cacheObject); dump(count($obj->cache)); exit;

Новое исключение ValueError


В PHP 8 появился новый встроенный класс исключений ValueError. Он дополняет собой \Exception. PHP бросает такое исключение каждый раз, когда вы передаёте функции значение правильного типа, однако его нельзя использовать в этой операции. Раньше в таких случаях выдавалось предупреждение. Примеры:

<?phpdeclare(strict_types=1); /** * We pass an array to array_rand, * which is of the correct type. But * array_rand expects non-empty arrays. * * This throws a ValueError exception. */array_rand([], 0); /** * The depth argument for json_decode is a * valid integer, but it must be greater than 0 */json_decode('{}', true, -1);

При определении функций можно использовать вариативный аргумент


Вариативным аргументом теперь можно заменить любое количество параметров функции, если их типы совместимы. Например, следующий код некорректен:

<?phpdeclare(strict_types=1); class A {    public function method(int $many, string $parameters, $here) {     }}class B extends A {    public function method(...$everything) {        dd($everything);    }} $b = new B();$b->method('i can be overwritten!');exit;

Возвращаемый тип static (RFC)


Возвращаемый тип static теперь можно использовать для определения ситуации, что метод возвращает класс, для которого этот метод и был вызван, даже если он был унаследован (позднее статическое связывание).

<?phpdeclare(strict_types=1); class Test {    public function doWhatever(): static {        // Do whatever.        return $this;    }} exit;

Литерал имени класса для объекта (RFC)


Теперь можно извлекать имя класса объекта с помощью $object::class. Результат будет такой же, как в случае с get_class($object).

<?phpdeclare(strict_types=1); auth()->loginUsingId(1); dump(auth()->user()::class); // Or with a temporary variable$user = auth()->user(); dump($user::class);exit;

Настройки синтаксиса переменных (RFC)


New и instanceof теперь можно использовать с произвольными выражениями: new (выражение)(...$args) и $obj instanceof (выражение).

<?phpdeclare(strict_types=1); class Foo {}class Bar {}  $class = new (collect(['Foo', 'Bar'])->random()); dd($class); exit;

Интерфейс Stringable (RFC)


В PHP 8 появился новый интерфейс Stringable, который добавляется автоматически, как только класс реализует метод __toString. Вам не нужно явно реализовывать этот интерфейс.

<?phpdeclare(strict_types=1); class Foo {    public function __toString() {        return 'I am a class';    }} $obj = new Foo;dump($obj instanceof Stringable); exit;

Теперь трейты могут определять абстрактные приватные методы (RFC)


<?phpdeclare(strict_types=1);  trait MyTrait {    abstract private function neededByTheTrait(): string;     public function doSomething() {        return strlen($this->neededByTheTrait());    }} class TraitUser {    use MyTrait;     // This is allowed:    private function neededByTheTrait(): string { }     // This is forbidden (incorrect return type)    // private function neededByTheTrait(): stdClass { }     // This is forbidden (non-static changed to static)    // private static function neededByTheTrait(): string { }} exit;

throw теперь можно использовать как выражение (RFC)


Выражение throw теперь можно использовать там, где допускаются только выражения: в стрелочных функциях, coalesce-операторах тернарных условных операторах (ternary/elvis).

<?phpdeclare(strict_types=1); $callable = fn() => throw new Exception(); $nullableValue = null; // $value is non-nullable.$value = $nullableValue ?? throw new \InvalidArgumentException();  exit;

В параметрах списка теперь допускается опциональная висящая запятая (RFC)


По аналогии с висящей запятой в массивах, теперь можно определять её и в параметрах списка.

<?phpdeclare(strict_types=1); function method_with_many_arguments(    $a,     $b,    $c,    $d,) {    dump("this is valid syntax");} method_with_many_arguments(    1,    2,    3,    4,); exit;

Ловля исключений без сохранения в переменной (RFC)


Теперь можно писать catch (исключение) для ловли исключений без их сохранения в переменной.

<?phpdeclare(strict_types=1); $nullableValue = null; try {    $value = $nullableValue ?? throw new \InvalidArgumentException();} catch (\InvalidArgumentException) {    dump("Something went wrong");}  exit;

Добавлена поддержка типа mixed (RFC)


В PHP 8 появился новый тип mixed. Он может быть эквивалентен типам array, bool, callable, int, float, null, object, resource, string.

<?phpdeclare(strict_types=1); function debug_function(mixed ...$data) {    dump($data);} debug_function(1, 'string', []); exit;

Добавлена поддержка атрибутов


Есть несколько предложений по внедрению атрибутов в PHP 8:


Это одно из крупнейших изменений в PHP 8. Возможно, сначала с ними не так легко будет разобраться. Если кратко, то атрибуты позволяют добавлять метаданные в PHP-функции, параметры, классы и т.д. Эти метаданные можно потом программно извлекать. Если в PHP 7 или ниже вам потребуется парсить doclock`и, атрибуты помогут обратиться к этой информации, глубоко интегрированной в сам PHP.

Чтобы было понятнее, представим, что вашим пользователям нужно дать возможность добавлять промежуточное ПО в контроллер класса или метода с помощью использования атрибута.

<?phpdeclare(strict_types=1);// First, we need to define the attribute. An Attribute itself is just a plain PHP class, that is annotated as an Attribute itself. #[Attribute]class ApplyMiddleware{    public array $middleware = [];     public function __construct(...$middleware) {        $this->middleware = $middleware;    }} // This adds the attribute to the MyController class, with the "auth" middleware as an argument. #[ApplyMiddleware('auth')]class MyController{    public function index() {}} // We can then retrieve all ApplyMiddleware attributes on our class using reflection// And read the given middleware arguments. $reflectionClass = new ReflectionClass(MyController::class); $attributes = $reflectionClass->getAttributes(ApplyMiddleware::class); foreach ($attributes as $attribute) {    $middlewareAttribute = $attribute->newInstance();    dump($middlewareAttribute->middleware);} exit;

Добавлена поддержка продвижения свойств конструктора (RFC)


Предложено добавить простой синтаксис, позволяющий комбинировать конструктор с определением свойств:

<?phpdeclare(strict_types=1); class User {    public function __construct(        public int $id,        public string $name,    ) {}} $user = new User(1, 'Marcel'); dump($user->id);dump($user->name); exit;

Добавлена поддержка выражения match (RFC)


Предложено добавить новое выражение match, которое аналогично switch, только с более безопасной семантикой и возможностью возвращать значения.

<?phpdeclare(strict_types=1); echo match (1) {    0 => 'Foo',    1 => 'Bar',    2 => 'Baz',}; exit;

Добавлена поддержка оператора nullsafe (?->) (RFC)


Когда результат левой части оператора равен null, исполнение всей цепочки останавливается, а её результат приравнивается к null. В противном случае цепочка ведёт себя как обычный оператор ->.

<?phpdeclare(strict_types=1); class User {    public function getAddress() {}} $user = new User(); $country = $user?->getAddress()?->country?->iso_code; dump($country); exit;

Добавлена поддержка именованных аргументов (RFC)


Именование позволяет передавать аргументы функции в зависимости от имени параметра, а не от его позиции. То есть значения аргументов становятся самодокументирующимися, а аргументы перестают зависеть от порядка перечисления, поэтому можно произвольно пропускать значения по умолчанию.

<?phpdeclare(strict_types=1); array_fill(start_index: 0, num: 100, value: 50); exit;
Подробнее..

PHP 8 Что нового?

25.11.2020 16:04:07 | Автор: admin

PHP, начиная с 7 версии, кардинально изменился. Код стал куда быстрее и надёжнее, и писать его стало намного приятнее. Но вот, уже релиз 8 версии! Ноябрь 26, 2020 примерно на год раньше, чем обещали сами разработчики. И всё же, не смотря на это, мажорная версия получилась особенно удачной. В этой статье я попытаюсь выложить основные приятные изменения, которые мы должны знать.


1. JIT


Как говорят сами разработчики, они выжали максимум производительности в 7 версии (тем самым сделав PHP наиболее шустрым среди динамических ЯПов). Для подальшего ускорения, без JIT-компилятора не обойтись. Справедливости ради, стоит сказать, что для веб-приложений использование JIT не сильно улучшает скорость обработки запросов (в некоторых случаях скорость будет даже меньше, чем без него). А вот, где нужно выполнять много математических операций там прирост скорости очень даже значительный. Например, теперь можно делать такие безумные вещи, как ИИ на PHP.
Включить JIT можно в настройках opcache в файле php.ini.
Подробнее 1 | Подробнее 2 | Подробнее 3


2. Аннотации/Атрибуты (Attributes)


Все мы помним, как раньше на Symfony код писался на языке комментариев. Очень радует, что такое теперь прекратится, и можно будет использовать подсказки любимой IDE, функция "Find usages", и даже рефакторинг!


Забавно, что символ # также можно было использовать для создания комментариев. Так что ничего не меняется в этом мире.

Было очень много споров о синтаксисе для атрибутов, но приняли Rust-like синтаксис:


#[ORM\Entity]#[ORM\Table("user")]class User{    #[ORM\Id, ORM\Column("integer"), ORM\GeneratedValue]    private $id;    #[ORM\Column("string", ORM\Column::UNIQUE)]    #[Assert\Email(["message" => "The email '{{ value }}' is not a valid email."])]    private $email;}

Подробнее 1 | Атрибуты в Symfony


3. Именованые параметры (Named Arguments)


Если вы когда-либо видели код, где есть булевы параметры, то понимаете насколько он ужасен. Ещё хуже, когда этих параметров 8 штук, 6 из которых имеют значение по-умолчанию, а вам нужно изменить значение последнего параметра.


К примеру, код для использования библиотеки phpamqplib:


$channel->queue_declare($queue, false, true, false, false);// ...$channel->basic_consume($queue, '', false, false, false, false, [$this, 'consume']);

С использованием именованых параметров, код становится намного легче читать:


$channel->queue_declare($queue, durable: true, auto_delete: false);// ...$channel->basic_consume($queue, callback: [$this, 'consume']);

Ещё несколько примеров:


htmlspecialchars($string, default, default, false);// vshtmlspecialchars($string, double_encode: false);

Внимание! Можно также использовать ассоциативные массивы для именованых параметров (и наоборот).


$params = ['start_index' => 0, 'num' => 100, 'value' => 50];$arr = array_fill(...$params);

function test(...$args) { var_dump($args); }test(1, 2, 3, a: 'a', b: 'b');// [1, 2, 3, "a" => "a", "b" => "b"]

Подробнее


4. Оператор безопасного null (Nullsafe operator)


Null сам по себе не очень хорошая штука (даже очень плохая). Когда функция возвращает null, то в каждом месте, где идёт её вызов, программист обязан проверить на null. И это приводит к ужасным последствиям.


$session = Session::find(123);if ($session !== null) {    $user = $session->user;    if ($user !== null) {        $address = $user->getAddress();        if ($address !== null) {            $country = $address->country;        }    }}

По хорошему, должен быть метод Session::findOrFail, который будет кидать исключение в случае отсутствия результата. Но когда эти методы диктует фреймворк, то мы не можем ничего сделать. Единственное, это проверять каждый раз на null либо, где это уместно, использовать ?->.


Да, с оператором nullsafe код станет немного лучше, но всё же это не повод возвращать null.

$country = $session?->user?->getAddress()?->country;

Этот код нельзя назвать чистым, только лишь от части. Для чистого кода, нужно использовать шаблон Null Object, либо выбрасывать exception. Идеальным вариантом было б:


$country = $session->user->getAddress()->country;

Поэтому, если возможно с вашей стороны, никогда не возвращайте null (к Римлянам 12:18).

Также интересным моментом в использовании nullsafe есть то, что при вызове метода с помощью ?->, параметры будут обработаны только если объект не null:


function expensive_function() {    var_dump('will not be executed');}$foo = null;$foo?->bar(expensive_function());

5. Оператор выбора match (Match expression v2)


Для начала покажу код до и после:


$v = 1;switch ($v) {    case 0:        $result = 'Foo';        break;    case 1:        $result = 'Bar';        break;    case 2:        $result = 'Baz';        break;}echo $result; // Bar

VS


$v = 1;echo match ($v) {    0 => 'Foo',    1 => 'Bar',    2 => 'Baz',};  // Bar

Как видим, это очень приятный оператор для выбора значений, который удобно заменяет switch.
Но есть очень важное отчилие switch от match: первый сравнивает нестрого ==, а во втором производится строгое === сравнение.


Наглядный пример различия:


switch ('foo') {    case 0:      $result = "Oh no!\n";      break;    case 'foo':      $result = "This is what I expected\n";      break;}echo $result; // Oh no!

VS


echo match ('foo') {    0 => "Oh no!\n",    'foo' => "This is what I expected\n",}; // This is what I expected

В PHP8 этот пример со switch работает по другому, далее рассмотрим это.

Также, сравниваемыми значениями оператора match могут быть выражения. При этом, будут выполнены только те, пока не будет найден первый совпадающий вариант:


$result = match ($x) {    foo() => ...,    $this->bar() => ..., // bar() isn't called if foo() matched with $x    $this->baz => ...,    // etc.};

6. Адекватное приведение строки в число (Saner string to number comparisons)


Проблема


$validValues = ["foo", "bar", "baz"];$value = 0;var_dump(in_array($value, $validValues));// bool(true) ???

Это происходит потому, что при нестрогом == сравнении строки с числом, строка приводится к числу, то-есть, например (int)"foobar" даёт 0.


В PHP8, напротив, сравнивает строку и число как числа только если строка представляет собой число. Иначе, число будет конвертировано в строку, и будет производиться строковое сравнение.


Comparison Before After
0 == "0" true true
0 == "0.0" true true
0 == "foo" true false
0 == "" true false
42 == " 42" true true
42 == "42foo" true false

Стоит отметить, что теперь выражение 0 == "" даёт false. Если у вас из базы пришло значение пустой строки и обрабатывалось как число 0, то теперь это не будет работать. Нужно вручную приводить типы.

Эти изменения относятся ко всем операциям, которые производят нестрогое сравнение:


  • Операторы <=>, ==, !=, >, >=, <, <=.
  • Функции in_array(), array_search(), array_keys() с параметром strict: false (то-есть по-умолчанию).
  • Сотрировочные функции sort(), rsort(), asort(), arsort(), array_multisort() с флагом sort_flags: SORT_REGULAR (то-есть по-умолчанию).

Также, есть специальные значения которые при нестрогом сравнении дают true:


Expression Before After
INF == "INF" false true
-INF == "-INF" false true
NAN == "NAN" false false
INF == "1e1000" true true
-INF == "-1e1000" true true

7. Constructor Property Promotion


Изначально идея позаимствована в языка-брата Hack. Она состоит в том, чтобы упростить инициализацию полей класса в конструкторе.


Вместо прописания полей класа, параметров конструктора, инициализации полей с помощью параметров, можно просто прописать поля параметрами конструктора:


class Point {    public function __construct(        public float $x = 0.0,        public float $y = 0.0,        public float $z = 0.0,    ) {}}

Это эквивалентно:


class Point {    public float $x;    public float $y;    public float $z;    public function __construct(        float $x = 0.0,        float $y = 0.0,        float $z = 0.0,    ) {        $this->x = $x;        $this->y = $y;        $this->z = $z;    }}

С этим всё просто, так как это синтаксический сахар. Но интересный момент возникает при использовании вариативные параметры (их нельзя объявлять таким образом). Для них нужно по-старинке вручную прописать поля и установить их в конструкторе:


class Test extends FooBar {    private array $integers;    public function __construct(        private int $promotedProp,         Bar $bar,        int ...$integers,    ) {        parent::__construct($bar);        $this->integers = $integers;    }}

8. Новые функции для работы со строками (str_contains, str_starts_with, str_ends_with)


Функция str_contains проверяет, содержит ли строка $haystack строку $needle:


str_contains("abc", "a"); // truestr_contains("abc", "d"); // falsestr_contains("abc", "B"); // false // $needle is an empty stringstr_contains("abc", "");  // truestr_contains("", "");     // true

Функция str_starts_with проверяет, начинается ли строка $haystack строкой $needle:


$str = "beginningMiddleEnd";var_dump(str_starts_with($str, "beg")); // truevar_dump(str_starts_with($str, "Beg")); // false

Функция str_ends_with проверяет, кончается ли строка $haystack строкой $needle:


$str = "beginningMiddleEnd";var_dump(str_ends_with($str, "End")); // truevar_dump(str_ends_with($str, "end")); // false

Вариантов mb_str_ends_with, mb_str_starts_with, mb_str_contains нету, так как эти функции уже хорошо работают с мутльтибайтовыми символами.


На самом деле, очень приятно, что наконец-то добавили эти функции. Теперь не нужно писать каждый раз своих костылей с помощью substr, strncmp, strpos.

9. Использование ::class на объектах (Allow ::class on objects)


Раньше, чтобы получить название класса, к которому принадлежит объект, нужно было использовать get_class:


$object = new stdClass;$className = get_class($object); // "stdClass"

Теперь же, можно использовать такую же нотацию, как и ClassName::class:


$object = new stdClass;var_dump($object::class); // "stdClass"

10. Возвращаемый тип static (Static return type)


Тип static был добавлен для более явного указания, что используется позднее статическое связывание (Late Static Binding) при возвращении результата:


class Foo {    public static function createFromWhatever(...$whatever): static {        return new static(...$whatever);    }}

Также, для возвращения $this, стоит указывать static вместо self:


abstract class Bar {    public function doWhatever(): static {        // Do whatever.        return $this;    }}

11. Weak Map


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


Интерфейс класса выглядит следующим образом:


WeakMap implements Countable , ArrayAccess , Iterator {    public __construct ( )    public count ( ) : int    public current ( ) : mixed    public key ( ) : object    public next ( ) : void    public offsetExists ( object $object ) : bool    public offsetGet ( object $object ) : mixed    public offsetSet ( object $object , mixed $value ) : void    public offsetUnset ( object $object ) : void    public rewind ( ) : void    public valid ( ) : bool}

Особенностью есть то, что объекты, используемые как ключи, подвержены сборке мусора. Поэтому, WeakMaps особенно пригодные для долгоживущих процессов.


class FooBar {    private WeakMap $cache;    public function getSomethingWithCaching(object $obj) {        return $this->cache[$obj] ??= $this->decorated->getSomething($obj);    }    // ...}

Подробнее можно почитать в документации.


12. Убрано возможность использовать левоассоциативный оператор (Deprecate left-associative ternary operator)


Рассмотрим код:


return $a == 1 ? 'one'     : $a == 2 ? 'two'     : $a == 3 ? 'three'     : $a == 4 ? 'four'              : 'other';

Вот как он всегда работал:


$a Result
1 'four'
2 'four'
3 'four'
4 'four'

В 7.4 код как прежде, отрабатывал, но выдавался Deprecated Warning.
Теперь же, в 8 версии, код упадёт с Fatal error.


13. Изменение приоритета оператора конкатенации (Change the precedence of the concatenation operator)


Раньше, приоритет оператора конкатенации . был на равне с + и -, поэтому они исполнялись поочерёдно слева направо, что приводило к ошибкам. Теперь же, его приоритет ниже:


Expression Before Currently
echo "sum: " . $a + $b; echo ("sum: " . $a) + $b; echo "sum :" . ($a + $b);

14. Удалены краткие открывающие php теги


В каждом скрипте, где в настоящее время используется короткий <? открывающий тег, нужно будет внести изменения и использовать стандартный тег <?php.


Это не касается тега <?=, так как он, начиная с 5.4 всегда доступен.


15. Новый интерфейс Stringable


Объекты, которые реализуют метод __toString, неявно реализуют этот интерфейс. Сделано это в большей мере для гарантии типобезопасности. С приходом union-типов, можно писать string|Stringable, что буквально означает "строка" или "объект, который можно преобразовать в строку". В таком случае, объект будет преобразован в строку только когда уже не будет куда оттягивать.


interface Stringable{    public function __toString(): string;}

Рассмотрим такой код:


class A{    public function __toString(): string     {        return 'hello';    }}function acceptString(string $whatever) {    var_dump($whatever);}acceptString(123.45); // string(6) "123.45"acceptString(new A()); // string(5) "hello"

Здесь функция acceptString принимает строку, но что если нам нужно конкретно объект, что может быть преобразован в строку, а не что-либо иное. Вот тут нам поможет интерфейс Stringable:


function acceptString(Stringable $whatever) {    var_dump($whatever);    var_dump((string)$whatever);}// acceptString(123.45); /*TypeError*/acceptString(new A()); /*object(A)#1 (0) {}string(5) "hello"*/

16. Теперь throw это выражение


Примеры использования:


// This was previously not possible since arrow functions only accept a single expression while throw was a statement.$callable = fn() => throw new Exception();// $value is non-nullable.$value = $nullableValue ?? throw new InvalidArgumentException();// $value is truthy.$value = $falsableValue ?: throw new InvalidArgumentException();// $value is only set if the array is not empty.$value = !empty($array)    ? reset($array)    : throw new InvalidArgumentException();

Подробнее можно почитать здесь.


17. Стабильная сортировка


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


Сюда входят sort, rsort, usort, asort, arsort, uasort, ksort, krsort, uksort, array_multisort, а также соответствующие методы в ArrayObject.


18. Возможньсть опустить переменную исключения (non-capturing catches)


Раньше, даже если переменная исключения не использовалась в блоке catch, её всё равно нужно быто объявлять (и IDE подсвечивала ошибку, что переменная нигде не используется):


try {    changeImportantData();} catch (PermissionException $ex) {    echo "You don't have permission to do this";}

Теперь же, можно опустить переменную, если никакая дополнительная информация не нужна:


try {    changeImportantData();} catch (PermissionException) { // The intention is clear: exception details are irrelevant    echo "You don't have permission to do this";}

19. Обеспечение правильной сигнатуры магических методов (Ensure correct signatures of magic methods):


Когда были добавлены type-hints в php, оставалась возможность непавильно написать сигнатуру для магических методов.
К примеру:


class Test {    public function __isset(string $propertyName): float {        return 123.45;    }}$t = new Test();var_dump(isset($t)); // true

Теперь же, всё жёстко контролируется, и допустить ошибку сложнее.


Foo::__call(string $name, array $arguments): mixed;Foo::__callStatic(string $name, array $arguments): mixed;Foo::__clone(): void;Foo::__debugInfo(): ?array;Foo::__get(string $name): mixed;Foo::__invoke(mixed $arguments): mixed;Foo::__isset(string $name): bool;Foo::__serialize(): array;Foo::__set(string $name, mixed $value): void;Foo::__set_state(array $properties): object;Foo::__sleep(): array;Foo::__unserialize(array $data): void;Foo::__unset(string $name): void;Foo::__wakeup(): void;

20. Включить расширение json по-умолчанию (Always available JSON extension)


Так как функции для работы с json постоянно используются, и нужны чуть ли не в каждом приложении, то было принято решение включить ext-json в PHP по-умолчанию.


21. Более строгие проверки типов при для арифметических и побитовых операторов (Stricter type checks for arithmetic/bitwise operators)


Проблема, которую разработчики здесь решили предоставлена кодом ниже:


var_dump([] % [42]);

Что должен вывести этот код? Здесь непредсказуемое поведение (будет 0). Всё потому, что большинство арифметических операторов не должны применятся на массивах.


Теперь, при использовании операторов +, -, *, /, **, %, <<, >>, &, |, ^, ~, ++, -- будет вызывать исключение TypeError для операндов array, resource и object.


22. Валидация абстрактных методов в трейтах (Validation for abstract trait methods)


До восьмой версии, можно было писать что-то вроде:


trait T {    abstract public function test(int $x);}class C {    use T;    // Allowed, but shouldn't be due to invalid type.    public function test(string $x) {}}

Начиная с восьмой версии, такой код будет падать с ошибкой. Да, и теперь есть возможность в трейте сделать приватный абстрактный метод, который будет реализован в использующем трейт классе.


trait MyTrait {    abstract private function neededByTheTrait(): string;    public function doSomething() {        return strlen($this->neededByTheTrait());    }}class TraitUser {    use MyTrait;    // This is allowed:    private function neededByTheTrait(): string { }    // This is forbidden (incorrect return type)    private function neededByTheTrait(): stdClass { }    // This is forbidden (non-static changed to static)    private static function neededByTheTrait(): string { }}

Случаи, когда реализация приходит из родительского класса, или трейт применён в родительском классе, также проверяются.


23. Объединения типов (Union Types 2.0)


Рассмотрим код:


class Number {    /**     * @var int|float $number     */    private $number;    /**     * @param int|float $number     */    public function setNumber($number) {        $this->number = $number;    }    /**     * @return int|float     */    public function getNumber() {        return $this->number;    }}

Здесь тип переменной $number контролируется только соглашениями программистов. На самом деле, туда может попасть что-угодно, и выйти отсюда может также что-угодно, так как проверки на тип не обеспечиваются ядром языка.


Теперь же, можно прописать тип int|float (или любой другой) явно, чтобы обеспечить корректность работы модуля:


class Number {    private int|float $number;    public function setNumber(int|float $number): void {        $this->number = $number;    }    public function getNumber(): int|float {        return $this->number;    }}

А также, код становится намного чище.
Как вы уже могли заметить, типы-объединения имеют синтаксис T1|T2|... и могут быть использованы во всех местах, где можно прописать type-hints.


Некоторые оговорки:


  • Тип void не может быть частью объединения.
  • Чтобы обозначить отсутствие результата, можно объявить "Nullable union type", который имеет следующий синтаксис: T1|T2|null.
  • Тип null не может быть использован вне объединения. Вместо него стоит использовать void.
  • Существует также псевдотип false, который по историческим причинам уже используется некоторыми функциями в php. С другой стороны, не существует тип true, так как он нигде не использовался ранее.

Типы полей класса инвариантны, и не могут быть изменены при наследовании.
А вот с методами всё немного интересней:


  1. Параметры методов можно расширить, но нельзя сузить.
  2. Возвращаемые типы можно сузить, но нельзя расширить.

Вот как это выглядит в коде:


class Test {    public function param1(int $param) {}    public function param2(int|float $param) {}    public function return1(): int|float {}    public function return2(): int {}}class Test2 extends Test {    public function param1(int|float $param) {} // Allowed: Adding extra param type    public function param2(int $param) {}       // FORBIDDEN: Removing param type    public function return1(): int {}           // Allowed: Removing return type    public function return2(): int|float {}     // FORBIDDEN: Adding extra return type}

То же самое происходит при типах, которые получились как результат наследования:


class A {}class B extends A {}class Test {    public function param1(B|string $param) {}    public function param2(A|string $param) {}    public function return1(): A|string {}    public function return2(): B|string {}}class Test2 extends Test {    public function param1(A|string $param) {} // Allowed: Widening union member B -> A    public function param2(B|string $param) {} // FORBIDDEN: Restricting union member A -> B    public function return1(): B|string {}     // Allowed: Restricting union member A -> B    public function return2(): A|string {}     // FORBIDDEN: Widening union member B -> A}

Интереснее становится когда strict_types установлен в 0, то-есть по-умолчанию. Например, функция принимает int|string, а мы передали ей bool. Что в результате должно быть в переменной? Пустая строка, или ноль? Есть набор правил, по которым будет производиться приведение типов.


Так, если переданный тип не является частью объединения, то действуют следующие приоритеты:


  1. int;
  2. float;
  3. string;
  4. bool;

Так вот, будет перебираться этот список с типами, и для каждого проверяться: Если тип существует в объединении, и значение может быть приведёно к нему в соответствии с семантикой PHP, то так и будет сделано. Иначе пробуем следующий тип.


Как исключение, если string должен быть приведён к int|float, то сравнение идёт в первую очередь в соответствии с семантикой "числовых строк". К примеру, "123" станет int(123), в то время как "123.0" станет float(123.0).


К типам null и false не происходит неявного преобразования.

Таблица неявного приведения типов:


Original type 1st try 2nd try 3rd try
bool int float string
int float string bool
float int string bool
string int/float bool
object string

Типы полей и ссылки


class Test {    public int|string $x;    public float|string $y;}$test = new Test;$r = "foobar";$test->x =& $r;$test->y =& $r;// Reference set: { $r, $test->x, $test->y }// Types: { mixed, int|string, float|string }$r = 42; // TypeError

Здесь проблема в том, что тип устанавливаемого значения не совместим с объявленными в полях класса. Для Test::$x это могло быть int(42), а для Test::$y float(42.0). Так как эти значения не эквивалентны, то невозможно обеспечить единую ссылку, и TypeError будет сгенерирован.


24. Тип mixed (Mixed Type v2)


Был добавлен новый тип mixed.
Он эквивалентен типу array|bool|callable|int|float|object|resource|string|null.
Когда параметр объявлен без типа, то его тип это mixed.
Но стоит отметить, что если функция не объявляет возвращаемого значения, то это не mixed, а mixed|void. Таким образом, если функция гарантировано должна что-то возвращать, но тип результата не известен заранее, то стоит написать его mixed.


При наследовании действуют следующие правила:


class A{    public function bar(): mixed {}}class B extends A{    // return type was narrowed from mixed to int, this is allowed    public function bar(): int {}}

class C{    public function bar(): int {}}class D extends C{    // return type cannot be widened from int to mixed    // Fatal error thrown    public function bar(): mixed {}}

Подробнее можно почитать здесь


Где смотреть новые фичи


Более информации про новые функции в PHP можно посмотреть на rfc watch.


IMHO хорошие идеи для PHP



С текущей реализацией PHP можно писать программы практически не используя переназначение переменной. Мы могли бы для каждого нового значения создавать свою собственную переменную. Тем самым код стал бы куда лучше понятным, так как для каждой переменной нужно дать имя в соответствии с тем, что там храниться. Но сейчас так никто не делает. Отчасти это потому что язык не позволяет ограничить переприсваивание значения.


Вот пример проблемного кода. Со временем значение изменяется, и при добавлении ещё какой-либо обработки велика вероятность сломать что-то на следующих строках:


$invoice = getInvoice();$invoice = loadDependencies($invoice);$invoice = formatInvoice($invoice);// hm... how do I access initial $invoice now?return $invoice;

Я вижу как минимум 4 недостатка в этом коде:


  1. Никогда точно не знаешь что в переменной;
  2. Невозможность использовать уже перезаписанное значение где-то дальше в коде;
  3. Неустойчивость к изменениям если производиться копипаст большой части кода с такими-же переменными где-то во вложенном if, тогда ночь отладки обеспеченна.
  4. Каждый раз нужно писать знак $ перед $переменной. Да, это спорно, но ведь без долларов проще читать код. Возьмите какого-либо джависта, что он скажет про ваш код? Уххх как много долларов!

Вот каким мог быть этот код:


invoice = getInvoice();invoiceWithDependencies = loadDependencies(invoice);invoiceFormatted = formatInvoice(invoiceWithDependencies);// someAnotherAction(invoice);return invoiceFormatted;

Значения, что содержатся в invoice, invoiceWithDependencies, invoiceFormatted не могут быть перезаписаны. Да, и теперь мы точно знаем что и где хранится.


function printArr(array arr) {    foreach (arr as firmValue) {        print strtr(            "Current value is {current}. +1: {next}",             [                '{current}' => firmValue,                 '{next}'    => firmValue + 1            ]        );    }}


use Spatie\ModelStates\State;abstract class OrderStatus extends State{    public static string $name = static::getName();    abstract protected function getName(): string;}

Как видим, при первом обращении к $name, будет вызван метод getName финального класса. Это дает нам возможность настраивать какие значения будут попадать в поля в зависимости от каких-либо условий. А в данном примере это использовано с шаблоном "Template Method", и финальные классы обязаны предоставить нам значение для поля.


Сейчас многие фреймворки имеют значени по-умолчанию для большинства конфигураций в своих классах. Проблема с таким подходом заключается в том, что мы можем предоставить только примитивное значение. Никаких вызовов функций не разрешено. А что если мы хотим вызвать хелпер config для предоставления конфигурации, которая задаётся в поле класса? Тогда у нас проблемы, и нужно переопределять конструктор, где уже задавать значение поля. Хорошо, когда конструктор не имеет много параметров. А что, если там много параметров (к примеру, 7)? Тогда для простого создания поля, нужно 20 дополнительных бесполезных строк кода. И выглядит это ещё как уродливо!


Просто сравните это:


    protected string $whatever = $this->doCalculate();

И это:


    public function __construct(        array $query = [],        array $request = [],        array $attributes = [],        array $cookies = [],        array $files = [],        array $server = [],        $content = null    ) {        parent::__construct(            $query,            $request,            $attributes,            $cookies,            $files,            $server,            $content        );        $this->whatever = $this->doCalculate();    }

Почему мы должны инициализировать поле в конструкторе, если оно не зависит от его параметров? Как по мне, мы не должны.

Подробнее..

Перевод Язык программирования PHP 8 новый JIT-компилятор нацелен на лучшую производительность

08.01.2021 02:22:10 | Автор: admin

Привет, Хабр. Будущих студентов курса "PHP-разработчик" и всех интересующихся приглашаем принять участие в открытом вебинаре на тему "PHP 8 Что нового?".

А сейчас делимся традиционным переводом интересного материала.


Старший эксперт по базам данных Google в восторге от JIT-компилятора, но остальные сомневаются в его значимости и говорят, что его сложно поддерживать.

Команда, создавшая скриптовый язык PHP, анонсировала версию PHP 8.0 крупный релиз, который может потребовать от разработчиков проверку кода на предмет критических изменений.

Эта версия 25-летнего PHP представляет улучшенную систему типов, новый JIT-компилятор в движке PHP и некоторые функции, заимствованные из Python и JavaScript, такие как именованные аргументы и null safe операторы.

PHP как язык не обрел всеобщей любви, но он широко используется веб-разработчиками. Разработчики оценивают PHP как шестой самый страшный язык в опросе разработчиков Stack Overflow 2020 года, но он также оказался восьмым по популярности языком.

Аналитик-разработчик RedMonk в настоящее время позиционирует PHP как четвертый по популярности язык, уступающий только Java, Python и JavaScript. Tiobe Software ставит PHP на восьмое место. И, по данным поисковой системы Indeed, количество объявлений о вакансиях PHP-разработчиков начального уровня за последний год увеличилось более чем на 800%.

PHP поддерживается основной группой разработчиков PHP и Zend, американской консалтинговой компанией по разработке PHP, основанной Энди Гутмансом, генеральным менеджером и вице-президентом по разработке баз данных в Google. Гутманс сказал, что он "в восторге" от JIT-компилятора.

JIT-компилятор предназначен для улучшения производительности веб-приложений. Однако Брент Руз, бельгийский разработчик stitcher.io, сказал, что у него есть нарекания, когда дело касается запросов.

Как у интерпретируемого языка, такого как JavaScript и Python, код PHP транслируется во время выполнения. Это не компилируемый язык, такой как C, Java или Rust, и его нужно транслировать, чтобы ЦП понимал код PHP.

JIT-компилятор может значительно улучшить производительность вашей программы, но сделать это правильно сложно, отметил Руз.

Плюсы JIT-компилятора заключаются в том, что он может сделать PHP лучшим языком для использования вне сети, но может затруднить отладку кода в компиляторе. Руз отметил, что в случае ошибки пользователи PHP будут зависеть от мейнтейнеров JIT-компилятора, что может означать более медленные исправления по части безопасности и багов.

Поскольку сегодня лишь несколько человек могут поддерживать кодовую базу [PHP], вопрос о том, возможно ли поддерживать JIT-компилятор как подобает, кажется оправданным. Конечно, люди могут разобраться в работе компилятора. Но, как ни крути, это сложный материал, сказал Руз.

Он сомневается, следует ли включать компилятор в PHP из-за затрат на обслуживание. Он также сказал, что пользователи PHP должны знать, что некоторые исправления ошибок или обновления версий могут занять больше времени, чем то, что мы привыкли ожидать на сегодняшний день.

Кроме того, выпуск PHP 8 в качестве мажорного релиза может означать, что старый код PHP может стать нерабочим после обновления. Однако Руз отметил, что большинство критических изменений объявлены устаревшими до версий 7.x.

Zend также опубликовал напоминание о том, что жизненный цикл PHP 7.2 подходит к концу 30 ноября 2020 года, а это означает, что основные контрибьюторы PHP больше не будут предлагать патчи безопасности для этой версии, что может создать проблемы для корпоративных веб-приложений.

Но пользователи PHP всегда могут заплатить консалтинговой фирме, такой как Zend, за долгосрочную поддержку, и они получат патчи после 30 ноября.

Что до пользователей операционных систем с предложениями долгосрочной поддержки, то их бинарники PHP зачастую продолжают получать патчи от поставщика ОС, даже когда заканчивается период поддержки сообщества", сказал Мэтью Вейер О'Финни, инженер Zend.

В случае с Ubuntu 18.04 и RHEL/CentOS 8, каждая из которых поставляется с PHP 7.2, это означает, что вы можете продолжать получать патчи. Однако если операционная система, в которой вы работаете, не находится под политикой LTS, тогда ваша версия со временем станет уязвимым для новых эксплойтов".

Марк Стори, главный разработчик Sentry, который поддерживает проекты PHP CakePHP и XHGui, сказал, что именованные параметры и типы объединения PHP 8 обеспечивают улучшения эргономичности и корректности.

Именованные параметры позволяют вызывать методы с параметрами на основе их имени, а не только их порядка, объяснил Стори.

Именованные параметры помогают упростить использование методов вызова, которые имеют множество необязательных параметров, поскольку вы можете указать только те параметры, которые используете по имени, сказал он ZDNet.

Это также поможет улучшить читаемость кода в будущем, так как запомнить, какой из параметров метода шестой труднее, чем понять, что может делать параметр expires.

Между тем, типы объединений расширяют систему типов PHP.


Узнать подробнее о курсе "PHP-разработчик".

Зарегистрироваться на открытый вебинар на тему "PHP 8 Что нового?".

Прямо сейчас в OTUS действуют максимальные новогодние скидки на все курсы. Ознакомиться с полным списком курсов вы можете по ссылке ниже. Также у всех желающих есть уникальная возможность отправить адресатуподарочный сертификат на обучение в OTUS.

Кстати, о "красивой упаковке" онлайн-сертификатов мырассказываем в этой статье.

ЗАБРАТЬ СКИДКУ

Подробнее..

Перевод PHP 8 продолжает развитие опенсорсного языка программирования

21.01.2021 16:23:47 | Автор: admin

Привет, Хабр! В преддверии старта курса PHP-разработчик приглашаем на открытый онлайн-урок по теме Что нового?. В рамках урока посмотрим на нововведения в языке и применим их на практике, а также посмотрим, так ли хорош JIT на самом деле.

А сейчас делимся традиционным переводом полезного материала.


Первое за последние годы крупное обновление широко распространенного языка веб-программирования PHP принесло нам новые фичи, которые могут помочь еще больше увеличить его распространенность и востребованность.

На заре эпохи интернета опенсорсный язык программирования PHP был в самом центре всей веб-разработки. Его новый релиз 8.0 стремиться сделать его более актуальным для нового поколения разработчиков.

Увидевший свет 25 лет назад, PHP представляет букву P в стеке LAMP (Linux, Apache, MySQL, PHP), который определил первое поколение веб-разработки. В последние годы другие языки, включая Python и JavaScript, начали превосходить PHP в популярности, в то время как новые языки, такие как Go и Rust, также очень быстро развиваются.

Однако PHP не сидит сложа руки, пока другие языки развиваются. PHP 8.0, который стал широко доступен в День благодарения (26 ноября), объединяет в себя ряд новых возможностей, в том числе механизм JIT-компиляции, который повышает производительность по сравнению с предыдущими версиями PHP.

Другие улучшения включают оптимизации языка, которые несомненно принесут пользу разработчикам, включая именованные аргументы и атрибуты.

PHP остается одним из наиболее распространенных скриптовых языков на сегодняшний день, - говорит Джеймс Оуэн, старший аналитик Evans Data, в интервью ITPro Today.

Любовь и ненависть к PHP

Согласно данным Global Development Survey 2020 от Evans Data (первой версии) 79% пользователей скриптовых языков используют PHP для какой-либо части своей работы, подразумевающей использование скриптового языка.

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

Востребованность PHP в различных отраслевых обзорах оценивается по-разному. Отчет RedMonk Programming Language Rankings за июнь 2020 года расположил PHP на четвертой позиции, после JavaScript, Python и Java. Индекс популярности языков программирования от TIOBE не столь щедр к PHP - он поставил его восьмым в своем листинге за ноябрь 2020 года.

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

PHP был создан в 1995 году разработчиком Расмусом Лердорфом, и с тех пор проект получил колоссальную поддержку от большого сообщества контрибьюторов. Одним из ведущих контрибьюторов и коммерческих сторонников PHP на протяжении последних двух десятилетий является компания Zend, занимающаяся инструментальными средствами разработки, которая теперь является частью Perforce Software.

Люди поздравляют меня с релизом PHP 8. Эти поздравления совершенно не по адресу, - писал Лердорф в твиттере на прошлой неделе. @nikita_ppv [Никита Попов из Jetbrains] и @dstogov [Дмитрий Стогов из Zend] уже много лет являются движущими силами развития PHP. Бесчисленное множество других разработчиков также регулярно вносят свою долю. PHP 8 значительно лучше, потому что он содержит намного меньше моего кода."

Какие фичи разработчики увидят в PHP 8

PHP был создан как веб-ориентированный язык, сообщил ITPro Today Мэтью Вейер О'Финни, продукт-менеджер Zend. Поскольку данные отправляются на веб-сайты через формы, все они поступают в виде строк, что означает, что PHP клонится в сторону так называемой динамической типизации и приведению типов, когда код может делать предположения о том, что было отправлено. Хотя динамическая типизация может быть весьма полезной, О'Финни говорит, что она также приводит к ошибкам и потенциальным проблемам безопасности.

Когда в 2015 году был выпущен PHP 7.0, в язык был добавлен ряд дополнительных функций, обеспечивающих строгую типизацию; в PHP 8.0 эти возможности расширяются. PHP 8 предоставляет так называемые "типы объединения" - способ указать, что аргумент или возвращаемое значение может иметь одним из набора типов, говорит О'Финни.

Что касается улучшения восприятия со стороны разработчиков, язык добавляет несколько функций, которые упростят общие паттерны, - добавил он.

Один из таких распространенных паттернов связан с практикой использования конструктора класса для присвоения свойств класса из предоставленных ему аргументов. В предыдущих релизах PHP, говорит О'Финни, разработчикам приходилось объявлять свойства, затем объявлять аргументы в конструкторе класса для каждого из них, а затем выполнять фактическое присвоение аргументов свойствам. Новая фича, называемая constructor property promotion, выполняет все это за одну операцию, определяя свойства из аргументов с помощью специального синтаксиса.

PHP 8.0 также получил систему атрибутов, над созданием которой, по словам О'Финни, работали очень долгое время. По его словам, во многих языках есть системы атрибутов или аннотаций, которые позволяют разработчикам определять метаданные об артефактах кода. Они используются такими вещами, как объектно-реляционные проекторы, чтобы разрешить сопоставление свойств класса со столбцами в базе данных или сопоставить путь веб-сервера к коду, который будет его обрабатывать. В PHP уже есть библиотеки для выполнения таких задач, но в PHP 8 теперь добавлена система атрибутов, которая запекает ее непосредственно в самом языке.

PHP 8 приходит как раз вовремя (Just in Time)

Новый JIT-компилятор (Just in Time) в PHP 8.0 вполне может помочь расширить распространение PHP.

JIT отлично подходит для численных вычислений и вещей, которые требуют больших вычислительных ресурсов, - говорит О'Финни. Однако PHP обычно используется для веб-приложений, которые не являются ни тем, ни другим.

Он отметил, что PHP имеет тенденцию быть ограниченным по вводу/выводу (I/O bound), где на производительность в первую очередь влияют такие вещи, как запросы к базе данных, кэширование значений, отправка запросов API или доступ к файловой системе. Однако JIT откроет дверь для использования PHP в приложениях, требующих более интенсивных вычислений.

В прошлом месяце PHP отпраздновал свое 25-летие, было выпущено восемь крупных релизов, и он по-прежнему отвечает за львиную долю того, что размещается в интернете, - говорит О'Финни. "Это стабильный, зрелый язык, который постоянно развивается, получая такие фичи, как JIT, которые позволят ему проникнуть в экосистемы, в которых ранее доминировали другие языки, такие как ML [машинное обучение], и из-за простоты, с которой его можно развернуть и низкого порога вхождения для разработчиков, он никуда не денется. Во всяком случае, будьте уверены, что PHP продолжит расти и развиваться.


Узнать подробнее о курсе PHP-разработчик.

Зарегистрироваться на онлайн-урок по теме Что нового?.

Подробнее..

Категории

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

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru