Свежая подборка со ссылками на новости и материалы. В выпуске: Enum в PHP 8.1, удаление Serializable и ограничение $GLOBALS, а также другие новости из PHP Internals, PhpStorm 2020.3, Symfony UX, порция полезных инструментов, видео, и первый PHP Дайджест Стрим.
Приятного чтения!
Новости и релизы
- PhpStorm 2020.3: PHP 8, атрибуты, PHPStan и Psalm, Xdebug 3, Tailwind CSS и совместная разработка.
- JetBrains Qodana EAP — Новый продукт от JetBrains для запуска PhpStorm в CI.
- Slack куплен за $27 млрд — Примечательно, то что бекенд Слэка изначально написан на PHP, а позже расширен на Hack.
- WordPress 5.6 — C бета-поддержкой PHP 8.
- Статистика версий PHP – 2020.2 — Традиционная подборка статистики на основе данных, которые Composer отправляет при подключении к packagist.org.
• PHP 7.4: 42.61% (+22.55)
• PHP 7.3: 27.05% (-3.00)
• PHP 7.2: 15.28% (-12.21)
• PHP 7.1: 7.45% (-4.1)
• PHP 5.6: 2.71% (-2.28)
• PHP 7.0: 2.70% (-1.30)
PHP Internals
- [RFC] Deprecate passing null to non-nullable arguments of internal functions — В текущих версиях PHP стандартные функции без ошибок принимают
null
в качестве аргумента даже, когда параметр неnullable
. Например,str_contains("", null)
Проблема в том, что если объявить пользовательскую функцию с такой сигнатурой, то там аргумент null вызовет ошибку.
str_contains("", null); // > No errors function _str_contains ( string $haystack , string $needle ) : bool { return true; } _str_contains("", null); // > Fatal error: Uncaught TypeError: Argument 2 passed to _str_contains() must be of the type string, null given
Предлагается поэтапно исправить это несоответствие и в 8.1 бросать deprecation notice.
Ну а пока можно добавитьdeclare(strict_types=1);
и проблема решена. - [RFC] Restrict $GLOBALS usage — Сейчас, чтобы
$GLOBALS
вел себя как массив, приходится поддерживать еще один специальный типINDIRECT
и предоставлять прямую ссылку на внутреннюю таблицу символов PHP. Поддержка этого влияет на производительность всех операций с массивами в PHP.
В этом RFC Никита Попов предлагает ограничить использование$GLOBALS
.
Продолжат работать чтение, запись, isset и unset:
$GLOBALS['x'] = 1; echo $GLOBALS['x'] isset($GLOBALS['x']); unset($GLOBALS['x']);
И он не будет содержать рекурсивную ссылку на самого себя.
А вот попытка изменить саму переменную $GLOBALS вызовет ошибку:
$GLOBALS = []; $GLOBALS =& $x; $x =& $GLOBALS; unset($GLOBALS);
Также ошибка будет, если передать$GLOBALS
по ссылке в функцию:
asort($GLOBALS); // > Compile-time error
Забавный факт: именно об этом говорил Дмитрий Стогов на стриме отвечая на вопрос: «что стоило бы убрать в следующих версиях PHP».
- [RFC] Phasing out Serializable — В 7.4 был введен новый механизм сериализации: наряду со старым интерфейсом
Serialiazable
были добавлены магические методы__serialize()
и__unserialize()
.
Предлагается постепенно полностью избавиться отSerializable
. В PHP 8.1 его использование будет генерировать deprecation notice, а в PHP 9.0 — compile-time error. - [RFC] Enumerations — Ilija Tovilo и Larry Garfield провели исследования enum во всех языках и представили RFC, который вдохновлен Swift, Rust, и Kotlin.
Enum это по сути класс, а его возможные значения — это объекты. Это означает, что, на вопрос «как бы вели себя Enums в ситуации X» можно ответить «так же, как и любой другой объект». Но есть несколько исключений.
Описывается с помощью ключевых словenum
иcase
:
enum Suit { case Hearts; case Diamonds; case Clubs; case Spades; }
Переменным можно присваивать одно из значений:
$val = Suit::Diamonds; function pick_a_card(Suit $suit) { ... } pick_a_card($val); // OK pick_a_card(Suit::Clubs); // OK pick_a_card('Spades'); // TypeError
Enum ведут себя как синглтон-объекты:
$a = Suit::Spades; $b = Suit::Spades; $a === $b; // true $a instanceof Suit; // true $a instanceof Suit::Spades; // true
Есть возможность объявить скалярные Enum. Их можно прозрачно использовать в контексте, где ожидаются скалярные значения:
enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S'; } echo "I hope I draw a " . Suit::Spades; // prints "I hope I draw a S".
Enum может иметь методы, в том числе статические. Пример использования метода для вывода списка опций чекбокса:
enum UserStatus: string { case Pending = 'pending'; case Active = 'active'; case Suspended = 'suspended'; case CanceledByUser = 'canceled'; public function label(): string { return match($this) { UserStatus::Pending => 'Pending', UserStatus::Active => 'Active', UserStatus::Suspended => 'Suspended', UserStatus::CanceledByUser => 'Canceled by user', }; } } foreach (UserStatus::cases() as $key => $val) { printf('<option value="%s">%s</option>\n', $key, $val->label()); }
Из открытых пока еще вопросов остаются:
- Могут ли иметь свои методы значения case?
- Можно ли использовать конкретное значение в качестве тайпхинта?
function stuff(Suit::Heart|Suit:Diamond $card) { ... }
- Разрешена ли сериализация Enum?
- < Должно ли слово
enum
быть полностью ключевым? Тогда сломается весь код, который использует имя классаEnum
. Или стоит сделать контекстное ключевое слово вот так:enum class UserStatus {...}
- [RFC] Algebraic Data Types — Предложение про Enum является первым шагом большого плана по реализации алгебраического типа в PHP. В качестве *возможных* дальнейших шагов рассматриваются tagged unions и pattern matching.
- [RFC] Direct execution opcode file without php source code file — Предлагается сделать возможным сохранять бинарный файл опкеша и запускать его уже без исходника. По сути, что-то очень похожее на питоновские файлы
.pyc / .pyo
.
Формат опкода в PHP нестабилен и несовместим от версии к версии. Чтобы решить эту проблему, предлагается скомпилированный таким образом файл помечать в начале меткой<?phpo%php_version_id%
.
Такой файл можно будет подключать через стандартные функцииinclude()
,include_once()
,require()
,require_once()
. - [RFC] Wall-Clock Time Based Execution Timeout — PHP измеряет всякого рода таймауты используя процессорное время. Это значит время затраченной в sleep() или сетевых запросах не учитывается. Например, это влияет на использование ini-настройки
max_execution_time
.
В данном RFC всего лишь предлагается ввести новую установкуmax_execution_wall_time
, которая бы учитывала реальное время вместо процессорного.
Инструменты
- itsgoingd/clockwork v5.0 — Отладочная панель и расширение для Chrome, которое добавляет вкладку в dev tools для отладки PHP-приложений. Подробный разбор инструмента смотрите в Пятиминутке PHP.
- nicofff/LazyIter — Библиотека для работы с массивами в виде цепочек вызовов. Вдохновленная итератором из Rust. Пост про строгую типизацию в поддержку.
- veewee/composer-run-parallel — Позволяет параллельно запускать команды из секции «scripts» в composer.json.
- clue/phar-composer — Берет проект с composer.json и создает исполняемый архив phar со всеми зависимостями.
- clue/commander — Для быстрого создания консольных команд.
- quasilyte/phpgrep 1.0 — Инструмент для поиска по PHP-коду – как grep, только с «пониманием» синтаксиса PHP.
Symfony
- Symfony UX — Новый инструментарий экосистеме Symfony для быстрого создания фронтенд-компонентов с помощью npm, Webpack Encore и Stimulus js. По сути предоставляются PHP+JS виджеты, которые устанавливаются через Composer: symfony/ux.
- Неделя Symfony #728 (7-13 декабря 2020)
- Делаем Action-Domain-Responder на Symfony
- Symfony и гексагональная архитектура
- Symfony Workshop 2020 — Пополняющийся курс по Symfony.
Laravel
- Представлен Laravel Sail — CLI-инструмент для работы запуска Laravel-приложений в Docker.
- tailflow/laravel-orion 1.0 — Пакет для автоматического создания REST API по Eloquent-моделям и их отношениям.
- asantibanez/laravel-eloquent-state-machines — Машина состояний (конечный автомат) для Eloquent моделей. Полезно, когда сущность может переходить из состояния в состояние по определенным правилам.
- lukeraymonddowning/honey — Инструмент-приманка для защиты от спама.
- Как обновить October CMS до Laravel 6?
- Стрим Laravel Internals #2 — с разработчиками из команды Laravel.
- Laravel at Scale: Framework, Community & Ecosystem — Интервью с Тейлором.
- Laravel–Дайджест (6–13 декабря 2020)
Yii
- Yii 1.1.23 — C поддержкой PHP 8.
- yiisoft/cookies — Еще один пакет из семейства Yii 3. Поможет при работе с куки-файлами в среде PSR-7.
- SOLID на практике. Принцип открытости-закрытости и ActiveQuery Yii2
Async PHP
- clue/reactphp-zenity — Обертка над Zenity для создания GUI приложений на PHP. Работает из коробки на Ubuntu.
Материалы для обучения
- Профилирование PHP-приложений на продакшне — Пост от разработчиков Wikipedia, о том как они используют два своих инструмента: wikimedia/php-excimer – сэмплирующий профайлер и wikimedia/arc-lamp – сборщик трейсов и генератор флейм-графиков.
We ingest about 3 million samples daily from a cluster of 150 Apache servers in any given data centre, using a 60s sample interval. These are all received by a single Redis instance.
- AWS Lambda теперь может запускать PHP, используя контейнеры Docker
- Переносим билды с Travis CI на GitHub Actions — Подборка ресурсов в связи с тем, что Travis CI изменил ценовую политику и теперь не бесплатный для опенсорса.
- php.watch: Детально о JIT в PHP 8
- Как должен выглядеть Faker 2.0 — Автор популярной библиотеки Faker прекратил работу над ней и теперь развивается форк. На обсуждение представлен документ с примерами использования следующей версии Faker.
- Руководство по разработке расширений для PHP от Zend
- НЕкостыль: gRPC-клиент на PHP в продакшене
- Сравним C++, JS, Python, Python + numba, PHP7, PHP8, и Golang на примере расчёта “Простое Число”
- Простой Telegram бот, который задаёт 1 вопрос
- Улучшаем архитектуру: Инверсия и внедрение зависимостей, наследование и композиция
- Масштабирование MySQL в Slack с помощью Vitess
- Книга «PHP для веба» от Matthias Noback теперь на русском. — Перевод книги подготовил lex111, один из мейнтейнеров русской документации PHP.
Аудио/Видео
- Видеокурс по PHP на 6.5 часов для абсолютных новичков
- Intro to PHP | Learn PHP The Right Way — Еще один видеокурс для новичков.
- Видеокурс ООП в PHP для новичков
- Пишем Блог на PHP — И еще для новичков.
- Что нового в PHP 8.0 — Подробный разбор новинок в PHP.
Занимательное
- Доступен в продаже новый слоник в честь 15-летия Symfony
Сегодня первый раз проведу стрим по PHP дайджесту. Все новости и ссылки из выпуска + больше деталей, обзор присланного, интересное но не вошедшее в выпуск, и конкурс со слониками.
Начало в 20:00 Москва, Минск / 19:00 Киев.
Если вы заметили ошибку или неточность — сообщите, пожалуйста, в личку хабра или телеграм.
Больше новостей и комментариев в Telegram-канале PHP Digest.
Прислать ссылку
Поиск ссылок по всем дайджестам
< Предыдущий выпуск: PHP-Дайджест № 193
VolCh
Ещё в архивчик запаковать… или phar адаптировать, чтоб php-fpm с ним работать мог.
vlreshet
pxz
Да, возможно в опенсорсе подобные решения создадут проблемы, но для коммерческой разработки — большой плюс.
Будет намного проще отдать клиенту "код" без костылей в виде обфускации (всё равно можно развернуть обратно). Текущие решения вроде Ioncube не работают с современными версиями php (7.4 / 8.0).
Тем более, в мире C++ (и не только) и скомпилированных библиотек с этим нет никаких проблем: библиотека поставляется вместе с заголовочником, схема отлаженная. Возможно, в php появится похожая возможность.
vlreshet
pxz
Ломают. И в нашем случае, скорее всего, научатся.
Тут вопрос в возможности использования такого декомпилированного кода и целесообразности таких действий.
Подождём, понаблюдаем. Но если появится нативный инструмент, который будет эту задачу решать и решать её хорошо, то пользы от этого будет точно больше, чем проблем. Всё же, в команде internals достаточно хороших и адекватных специалистов.
Grikdotnet
Это может быть нужно авторам платных коробок.
Для inhouse-разработки смысла в пред-компиляции немного, усложнится SDLC.
Разве что поверх PHP появится аналог Typescript.
VolCh
Интересная мысль. Правада, скорее не не аналог Typescript, а аналог Scala, Kotlin, JPython и т. п.
pxz
Всё верно.
Я рассуждал с мыслью о платных коробках. Когда при продаже ПО клиенту можно не переживать, что через несколько месяцев он будет выложен на какой-нибудь warez-помойке в комплекте с парочкой троянов.
Иногда условия бизнеса не позволяют создать какое-то SAAS-решение, клиент борется за то, чтобы софт был на его сервере и под его контролем.
zorn_v
Прощай использование
__DIR__, __FILE__
и прочих… Совсем нет проблем, ага, учитывая что сейчас сложно найти код не использующий эти константы (напримерrequire __DIR__ .'/vendor/autoload.php'
)А вот польза сомнительная. Насчет "защиты от чужих глаз" уж точно — декомпилировать опкоды PHP по моему уже давно умеют, если не ошибаюсь.
VolCh
Почему прощай-то? Просто компилировать нужно будет сразу в продакшен-путях: chroot, docker и ко.
roxblnfk
В bcompiler решали подобные проблемы добавлением заголовков в бинарные файлы. В этих заголовках и были прописаны пути до файлов и прочая метаинформация.
Насчёт __FILE__ и __DIR__ не помню, но ошибки точно вываливались с теми путями, которые были на машине разработчика в момент компиляции :)
Кроме того, нет особого смысла байткодить все файлы. Всякие штуки вроде
require __DIR__ .'/vendor/autoload.php'
можно было бы и вынестиSpy_W
Можно еще называть такие файлы
SomeClass.min.php
.pda0
Такие штуки уже существуют от сторонних разработчиков.