PHP и Laravel дайджест новостей за сентябрь 2024 года

Всем привет!

Это дайджест новостей от CutCode. Давайте посмотрим, что произошло за прошедший месяц в мире PHP и Laravel.

Новости PHP

Первый релиз-кандидат PHP 8.4 доступен для тестирования

Релиз-менеджеры Calvin Buckley, Saki Takamachi и Eric Mann создали ветку PHP-8.4, теперь разработка будет вестись в ней, а master ветка теперь нацелена на следующую версию PHP. Перед финальным выпуском, который ожидается 21 ноября, нас ожидает еще 3 релиз-кандидата.

Вышли PHP 8.1.30, PHP 8.2.24 и PHP 8.3.12

В этих выпусках исправлены:

  • Уязвимость инъекции параметров в CGI (CVE-2024-8926).
  • Обход из-за коллизии переменной окружения директивы cgi.force_redirect (CVE-2024-8927).
  • Возможность изменения логов от дочерних процессов FPM (CVE-2024-9026).
  • Ошибки при разборе данных многокомпонентных форм (CVE-2024-8925).

Пожалуйста, обновитесь, как можно скорее.

PHP-линч #22

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

PHP Russia 2024

2 и 3 декабря в Москве пройдёт конференция Highload, в рамках которой 16 докладов будут выделены под PHP Russia. Список докладов уже опубликован на сайте конференции.

Laravel привлёк $57 млн в рамках серии A от Accel

Сразу после Laracon US Taylor Otwell опубликовал твит, в котором объявил об инвестициях в размере 57 миллионов долларов от Accel, известной венчурной компании. Поздравляем Тейлора и команду!

Кстати, Роман Пронский побывал на Laracon US и пообщался с разными ребятами из PHP-сообщества:

Новости ядра PHP

Большинство новостей ядра PHP подробно освещаются в серии PHP Core Roundup от PHP Foundation, мы лишь быстро по ним пробежимся:

📣RFC: Deprecate json_encode() on classes marked as non-serializable

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

Однако этот флаг в настоящее время игнорируется функцией json_encode(), которая является другим способом сериализации, встроенным в PHP.

Philip Hofstetter предлагает запретить сериализовать с помощью функции json_encode() большинство экземпляров классов, отмеченных флагом ZEND_ACC_NOT_SERIALIZABLE и выдавать предупреждение об устаревании, начиная с PHP 8.5.

📣RFC: Change Directory class to behave like an opaque object

Класс Directory, вероятно, является первым экземпляром того, что мы сейчас называем «непрозрачным объектом». Непрозрачные объекты обычно являются результатом преобразования ресурсов в объекты, что в общем случае подразумевает, что они являются окончательными, не сериализуемыми, не инициализируемыми с помощью ключевого слова new, не могут быть приведены и не реализуют никаких методов. Однако, поскольку этот класс существует со времен PHP 4, ничего из этого формально не реализовано.

Gina Peter Banyard предлагает изменить класс Directory:

  • Пометить его окончательным.
  • Выбрасывать ошибку при инициализации с помощью ключевого слова new.
  • Предотвратить клонирование экземпляров класса Directory.
  • Запретить сериализацию с помощью doc-комментария @not-serializable к заглушке класса.
  • Запретить создание динамических свойств для экземпляра класса Directory с помощью doc-комментария @strict-properties к заглушке класса.

📣RFC: Warn on conversions from resource to string

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

Учитывая, что ресурсы постепенно уходят в сторону непрозрачных объектов и не поддерживают преобразование в строки, Gina Peter Banyard предлагает выдавать ошибку уровня E_WARNING, при преобразовании ресурса в строку.

Laravel дайджест

Обновления Laravel

11.22 Eloquent inverse relations

PR, который затрагивает Eloquent и добавляет новый метод, о котором говорил Taylor на последнем Laracon. Он называется Chaperone. Он решает проблему N+1.

Давайте рассмотрим пример:

@foreach($post->comments as $comment) <!-- comment content --> @can('promote', $comment) <a href="{{ route('posts.comments.promote', [$post, $comment]) }}">promote</a> @endcan @endforeach

У нас есть посты, мы также добавляем eager load с комментариями и вынуждены также добавлять eager load с родительским постом у комментариев, чтобы не попасть на исключение при strict mode и в целом, не плодить запросы. Хотя казалось бы, у нас и так есть родительская модель и логично было бы ее засетить ко всем загруженным комментариям. Как раз метод Chaperone это и делает. В pull request он называется inverse, в последующем он был переименован, а также добавлен, видимо, для обратной совместимости. И суть в итоге в том, что мы проходимся по всем загруженным моделькам и делаем set relation родительской записи. Я думаю, многие из вас это делали вручную. Теперь сможем ускорить процесс с помощью нового метода.

11.22 Allow enums to be passed to routes

Pull request добавляет поддержку указания name в route через enum. Ниже приведен пример:

// before Route::domain(InterfaceDomain::Marketing->value)->name(Routes::Home->value)->get('/contact', ContactController::class); // after Route::domain(InterfaceDomain::Marketing)->name(Routes::Home)->get('/'contact, ContactController::class);

До этого приходилось вызывать value, теперь можно просто указать enum и под капотом все сработает.

11.23 Adding minRatio & maxRatio rules on Dimension validation ruleset

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

function ($attribute, $value, $fail) { [$width, $height] = getimagesize($value->getPathname()); $aspectRatio = $width / $height; if ($aspectRatio > 1 / 2 || $aspectRatio < 1 / 3) { $fail("The image aspect ratio must be between 1:2 and 1:3."); }

11.23 Add BackedEnum support to Gate methods

Снова Enum. На этот раз не Route, а Gates, и мы также можем объявлять и далее во многих методах взаимодействовать с Gates через Enum. Как видим в примерах, до этого через строку, теперь то же самое можем делать с Enum, который возвращает строку и соответственно в методах указывать именно enum. Отлично, гораздо удобнее, чтобы не держать эти строки в памяти.

enum Abilities: string { case VIEW_DASHBOARD = 'view-dashboard'; case EDIT = 'edit'; case UPDATE = 'update'; } // Before Gate::define('view-dashboard', function (User $user) { return $user->isAdmin; }); Gate::authorize('view-dashboard'); Gate::inspect('view-dashboard'); Gate::check('view-dashboard'); Gate::any(['edit', 'update], $post); Gate::none(['edit', 'update]], $post); Gate::allows('update', $post) Gate::denies('update', $post) // After Gate::define(Abilities::VIEW_DASHBOARD, function (User $user) { return $user->isAdmin; }); Gate::authorize(Abilities::VIEW_DASHBOARD); Gate::inspect(Abilities::VIEW_DASHBOARD); Gate::check(Abilities::VIEW_DASHBOARD); Gate::any([Abilities::EDIT, Abilities::UPDATE], $post); Gate::none([Abilities::EDIT, Abilities::UPDATE], $post); Gate::allows(Abilities::UPDATE, $post) Gate::denies(Abilities::UPDATE, $post)

11.23 Add BackedEnum support to Authorize middleware

Двигаемся дальше по релизу 11.23. Снова Enum. И теперь они также допускаются в объекте Authorize методе using.

Route::get('/dashboard', [AdminDashboardController::class, 'index'])->middleware(Authorize::using(Abilities::VIEW_DASHBOARD))->name(AdminRoutes::DASHBOARD);

11.23 Add Skip middleware for Queue Jobs

Pull request добавляет новый middleware для очередей, который называется Skip. С помощью него можно в методы when и unless указывать условия, при выполнении которых выполнение очереди будет пропускаться. Нам показывают также пример, что раньше автор решал проблему пропуска через замыкание и соответственно сделал middleware, чтобы не дублировать эту логику, хотя в целом и непонятно, почему не добавить условия просто в handle.

class MyJob implements ShouldQueue { use Queueable; public function handle(): void { // TODO } public function middleware(): array { return [ function ($job, $next) { if ($someCondition) { $next($job); } }, ]; } }

11.23 Add Eloquent\Collection::findOrFail

Следующий pull request затрагивает коллекции Eloquent, в которых добавлен метод findOrFail. У новичков часто возникает проблема - после совершения запроса, который возвращает коллекцию с данными, новичок продолжает дергать методы queryBuilder, ожидая, что у нас все еще queryBuilder, а не коллекция, и натыкается на ошибку. Метод findOrFail у нас уже и есть коллекция и он будет по ID искать нужные модельки в этой коллекции. Но я думаю, есть вероятность, что это только добавит путаницы для новичков, но в целом вот такой сахар добавили в Eloquent коллекции.

$users = User::get(); // [User(id: 1), User(id: 2)] $users->findOrFail(1); // User $user->findOrFail([]); // [] $user->findOrFail([1, 2]); // [User, User] $user->findOrFail(3); // ModelNotFoundException: 'No query results for model [User] 3' $user->findOrFail([1, 2, 3]); // ModelNotFoundException: 'No query results for model [User] 3'

Laracon 2024

Далее у нас огромный pull request от Taylor, на котором я уже сделал обзор на канале, обязательно посмотрите. Это Helper Defer, фасад Concurrency и метод Flexible у кэша. Мы разобрали все подробно, заглянули под капот - обязательно посмотрите ролик на канале.

11.23 New when() helper

И напоследок по релизу 11.23 это новый Helper When, хотя не совсем Helper, а Blade-директива, благодаря которой можно указать условия и вторым параметром вывести определенные данные, как мы это видим в примерах в этом pull request.

<div @when($condition, 'wire:poll.5s="myMethodName"', false)> <input name="phone" @when($isRequired, 'required') />

11.24 add nullOnUpdate() method to ForeignKeyDefinition

Pull request затрагивает Schema. До этого у нас был nullOnDelete(), также добавлен и nullOnUpdate(). Кто ожидал - новый сахар добавлен.

$table->foreign('user_id') ->references('id') ->on('users') ->nullOnUpdate();

11.24 Allow BackedEnum to be passed to Route::can()

Снова Enum, снова роуты. Метод can() также принимает Enum начиная с этого релиза.

11.25

Также появился релиз 11.25, но он исключительно из фиксов и ревертов, ничего интересного.

Видео-версия дайджеста:

Начать дискуссию