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

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

Новости

❗В этих выпусках исправлены уязвимости CVE-2024-1874, CVE-2024-2756 и CVE-2024-3096, в PHP 8.3.6 также исправлена уязвимость CVE-2024-2757, которые исправляют:

  • Обход функции proc_open в Windows с экранированием аргументов для bat- и cmd-файлов
  • Обход куки __Host / __Secure
  • Бесконечный цикл в функции mb_encode_mimeheader
  • Обработка функцией password_hash значения $password с нулевым символом.

❗Версия PHP 8.3.5 была пропущена, пожалуйста, не полагайтесь этот тег.

Шумиха вокруг CVE-2024-2961, связанная с PHP, была крайне преувеличена. У многих сложилось впечатление, что уязвимость существует в самом языке и оказывает огромное влияние на PHP-разработчиков. Однако это не так.

Уязвимость может быть удаленно использована только в том случае, если приложение использует функции и потоковые фильтры модуля iconv с не валидированными кодировками, полученными из внешних источников.

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

Если вы не следили за этой историей, то вот вкратце, что произошло.

Некто под GitHub-аккаунтом @JiaT75 в течение 2 лет вносил свой вклад в библиетеку liblzma, создавая SSH-бэкдор незаметно для других сопровождающих. Он сделал более 700 коммитов, из которых лишь небольшое количество было вредоносным и спрятано в тестовых файлах. Странное поведение было случайно обнаружено при проведении микробенчмаркинга утилиты xz.

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

PHP Foundation будет сотрудничать с фондами Apache, Eclipse, Rust и Python для создания стандартов для закона о киберустойчивости.

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

Главные новинки этой версии:

  • Автодополнение строки целиком с помощью локального ИИ
  • Поддержка Symfony AssetMapper
  • Новый терминал
  • Улучшения для Pest
  • Поддержка PHPUnit 11.0

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

Хуки стали одним из самых больших и обсуждаемых RFC, в одном из предыдущих выпусках мы о них уже упоминали.

Они позволят разработчикам переопределять стандартное поведение "get" и "set" свойств объекта. Ларри Гарфилд и Илия Товилло вдохновлялись языками Kotlin, C# и Swift при разработке этого RFC.

RFC был принят подавляющим большинством голосов и мы с нетерпением ждем хуки в PHP 8.4.

RFC Валентина Удальцова, о котором мы говорили в конце прошлого года, перешел в стадию обсуждения.

У RFC положительные отзывы, ждем начала голосования, один голос у Валентина уже точно есть :)

На PHP-викторине, о которой мы поговорим чуть позже, Валентин также рассказал о своем RFC.

Джошуа Рюсвег (Joshua Rüsweg) предлагает добавить новую функцию для поиска первого элемента, для которого callback-функция возвращает значение true.

Тим Дюстерхус (Tim Düsterhus) предлагает пересмотреть предыдущее решение RFC по именованию классов. Вместо того, чтобы относиться к аббревиатурам как к обычным словам, сделать имена классов согласованными с PascalCase.

RFC о котором мы говорили в прошлом выпуске принят.

Сейчас PHP поддерживает два способа распространения идентификатора токена сессии: с помощью файлов cookie и с помощью параметров GET или POST.

В PHP 8.4, если параметр session.use_only_cookies отключен, а параметр session.use_trans_sid – включен, будет выдаваться предупреждение об устаревании.

В PHP 9.0 распространение идентификатора токена сессии с помощью параметров GET или POST будет удалено.

Поддержка безопасности для версий PHP увеличена на один год. Таким образом, каждая версия PHP будет поддерживаться 4 года: 2 года исправлений ошибок и 2 года исправлений безопасности.

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

По традиции, PHP 8.4 будут сопровождать два «новичка» релиз-менеджера: Саки Такамачи (Saki Takamachi), core-разработчик, поддерживаемая PHP Foundation, и Кельвин Бакли (Calvin Buckley), разработчик нескольких модулей PECL.

Им будет помогать ветеран релиз-менеджер PHP 8.3 Эрик Манн (Eric Mann).

Валентин Удальцов, Алексей Гагарин и Петр Мязин ответили на каверзные вопросы по PHP.

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

Сервис от CutCode по деплою приложений в один клик с нулевым временем простоя и контролем результата. Возможности аналогичные Envoyer, плюс есть дополнительные фичи. Подходит для деплоя приложений на PHP и Go.

Laravel дайджест

Обновления Laravel

11.2. Add fluent helper

PR на тему Fluent объекта. Что за Fluent такой? Это дополнительный сахар. Там где у нас коллекции не справляются с сахаром, на помощь приходит Fluent объект. Давайте взглянем на примеры. Скажем, у нас есть коллекция.

Есть метод Get. Элемент массива с Fluent мы можем просто указывать как свойство объекта и получать также доступ:

$data = [ 'user' => [ 'name' => 'Philo', 'address' => [ 'city' => 'Amsterdam', 'country' => 'Netherlands', ] ], 'posts' => [ [ 'title' => 'Post 1', ], [ 'title' => 'Post 2', ] ] ]; ❌ collect($data)->get('user'); ✅ fluent($data)->user

Далее у нас в коллекциях через метод Get не поддерживается вложенность через метод DataGet во Fluent объекте. Теперь такая возможность есть, через точку можем обращаться к вложенным элементам:

❌ collect($data)->get('user')['name']; ✅ fluent($data)->get('user.name');

Также есть возможность Fluent объект трансформировать в коллекции:

❌ collect(collect($data)->get('posts'))->pluck('title'); ✅ fluent($data)->collect('posts')->pluck('title');

И присутствует интересный метод Scope, который у нас под капотом содержит метод get, но возвращает новый instance fluent-объекта. И также нам демонстрирует пример, как удобно с помощью fluent-helper сделать JSON-Encode.

❌ json_encode(collect($data)->get('user')['address']); ✅ fluent($data)->scope('user.address')->toJson();

11.2. Add a new helper for context

Следующий PR затрагивает context. У нас уже был context фасад. И пришло время для helper для функции context:

context(['user' => auth()->user()]); // Add user information to the context $context = context(); // Retrieve the context object $user = context('user'); // Retrieve user information from the context

11.2. Add default value for get and getHidden on Context

Еще один PR по Context . У нас были методы-геттеры для получения элементов из контекста get и get-hidden. Но при этом мы не могли с вами указать дефолтное значение. Если такого ключа в контексте нет, то мы получаем с вами null:

$isUser = Context::get('is_user'); // If is not has in array return null forever $isUser = Context::getHidden('is_user'); // If is not has in array return null forever

Не совсем привычно для гетеров в Laravel, так как всегда присутствует вторым параметром дефолтное значение, и теперь оно есть и в Context:

$isUser = Context::get('is_user', false); // If is not has in array return false $isUser = Context::getHidden('is_user', false); // If is not has in array return false

11.2. Trim invisible characters

PR затрагивает Middlewar trim strings. До этого была проблема, невидимые Unicode символы Trimstrings не чистил. PR решает эту проблему.

11.2. Do not wipe database if it does not exists

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

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

11.2. Str trim methods

Следующий PR добавляет новый сахар в класс по работе со строками. Раньше был trim(), теперь есть ltrim() и rtrim().

11.3. Add Component: Multiline Text Input

Новая фича в Laravel Prompts. Обожаю этот пакет, и теперь появился элемент формы textarea() с помощью которого можем в консоли пользоваться текстовым блоком.

11.3. Add pull methods to Context

Этот PR добавляет в Context новый метод pull и pullHidden. Как и во всех pull в Laravel мы забираем значение из указанного элемента и после удаляем его из Context.

11.3. Add session hasAny method

В объект сессий добавили метод hasAny, чтобы не плодить условия или и указать все в массиве через новый метод:

До:

if (session()->has('first_name') || session()->has('last_name')) { // do something... }

После

if (session()->hasAny(['first_name', 'last_name'])) { // do something... }

11.4. Introduces Exceptions facade

PR от Nuno Maduro, новый фасад exceptions, который даст нам новые возможности в тестировании exception. В примерах показано, как в тестах мы можем переключить exceptions в fake и далее в тестах проверять, вызваны ли исключения, сколько раз вызваны, и так далее.

11.4. Allowing Usage of Livewire Wire Boolean Style Directives

Следующий pull request, для фанатов livewire. Теперь в Blade-директивы можно будет отправлять параметры в boolean стиле. До этого при генерации HTML у нас добавлялся value:

{{-- Using like this --}} <x-fetch wire:poll /> {{-- Generates this HTML --}} <div ... wire:poll="wire:poll" />

Теперь же у нас если нет значения, то и при рендере его не будет:

11.4. afterQuery hook

Следующий pull request добавляет новый метод в queryBuilder — autoquery, который исходя из названия будет вызван после того, как будет вызван запрос.

В pull request показан пример, где есть scope и мы после запроса итерируем продукты и устанавливаем определенный атрибут.

public function scopeWithIsFavoriteOf($query, ?User $user = null) : void { if ($user === null) { return $query; } $query->addSelect([ // 'is_favorite' =&gt; some query ... ]); } $products = Product::withIsFavoriteOf(auth()->user())->get(); if (auth()->user() === null) { $products->each->setAttribute('is_favorite', false); }

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

public function scopeWithIsFavoriteOf($query, ?User $user = null) : void { if ($user === null) { $query->afterQuery(fn ($products) => $products->each->setAttribute('is_favorite', false)); return; } $query->addSelect([ // 'is_favorite' => some query ... ]); } Product::withIsFavoriteOf(auth()->user())->get();

11.4. Add RequiredIfDeclined validation rule

Следующий pull request добавляет правила валидации requiredIfDeclined. У нас уже был requiredIfAccepted, теперь появился его “брат” - если у нас checkbox не выбран.

11.4. Adds support for enums on mapInto collection method

В следующем pull request речь пойдет методе mapInto для коллекций. Теперь мы можем мапить в enum данные:

public function store(Request $request) { $request->validate([ 'features' => ['array'], 'features.*' => [new Enum(Feature::class)], ]); $features = $request -&gt;collect('features') -&gt;mapInto(Feature::class); if ($features-&gt;contains(Feature::DarkMode)) { // 🌙 } }

11.4. Adds Reversible Forms to Prompts

В Laravel Prompts добавилась новая фича. До этого мы могли через Form Builder, через Helper Form, строить формы и получать значение из всех элементов формы только после сабмита:

$responses = form() ->text('What is your name?') ->select('What is your favourite language?', ['PHP', 'JS']) ->submit();

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

$responses = form() ->text('What is your name?') ->select('What is your favourite language?', ['PHP', 'JS']) ->add(fn ($responses) => note("Your name is {$responses[0]} and your language is {$responses[1]}")) ->submit();

11.5. Supercharge Blade

PR, который затрагивает Blade, и ускоряет его работу. Теперь Blade будет работать в 15-25 раз быстрее.

11.5. Blade Component Loop Speed Improvement

PR оптимизирующий loop внутри Blade - скорость увеличена на 7%.

11.5. Ability to generate URL's with query params

PullRequest, который затрагивает URL-генератор. Появился новый метод Query, с помощью которого можно удобно строить URL вместе с Query-параметрами:

// http://localhost/products?sort=-name url()->query('products', ['sort' => '-name']); // http://localhost/products?columns[0]=name&columns[1]=price&columns[2]=quantity url()->query('products', ['columns' => ['name', 'price', 'quantity']]);

Много возможностей, как видим из примеров. Крутая фича для URL генератора.

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

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