Всем привет!
Это PHP Дайджест на канале CutCode. Давайте посмотрим, что произошло за прошедший месяц в мире PHP.
Новости PHP
Релизы PHP
Вышли PHP 8.4.11, PHP 8.3.25, выпуски с исправлением ошибок вышли по расписанию.
Также в начале месяца вышли PHP 8.2.29 и PHP 8.1.33.
В этих выпусках безопасности исправлены следующие уязвимости:
GHSA-hrwm-9436-5mv3 – Проверка наличия ошибок во время экранирования в модуле pgsql
GHSA-453j-q27h-5p8x – Разыменование указателя NULL в модуле PHP SOAP с помощью большого префикса пространства имен XML
GHSA-3cr5-j632-f35r – Нулевой байт завершения в именах хостов
PHP 8.5.0 Alpha 3
Все три альфа-версии PHP 8.5.0 вышли по расписанию. Заморозка функций произойдет 12 августа, поэтому некоторые изменения могут попасть в релиз.
Наиболее заметные изменения на данный момент:
Оператор конвейера (
|>
)Модификатор
final
для свойств, которые объявляются в конструктореНовые функции
array_first()
иarray_last()
Новый атрибут
#[\NoDiscard]
Замыкания в постоянных выражениях
Языковая конструкция
clone with
…и многое другое!
PER Coding Style 3.0
Вышла новая версия руководства по стилю кодирования PHP. Посмотрите руководство по миграции с PER-CS v2.0 на PER-CS v3.0.
Не могу пройти мимо четвертого раздела: «При использовании PHP 8.4 или более поздней версии скобки вокруг объявления new должны быть опущены» – поздравляю Валентина Удальцова с этим изменением.
Пых.конф
19 сентября в Москве в Центре Международной Торговли пройдёт новая PHP-конференция – Пых.конф.
Единственная в этом году профильная конференция в русскоговорящем IT-сообществе, которая целиком и полностью посвящена PHP.
В программе заявлено 28 докладов, вот некоторые из них:
Кирилл Несмеянов покажет, как писать десктопные приложения на PHP
Андрей Клименко (HappyJob) вскружит голову функциональным программированием
Александр Макаров (Twindo) расскажет про внутрянку Yii3
Дмитрий Edmond поделится прогрессом RFC True Async
Вадим Занфир (VK) научит имплементировать на PHP любые протоколы в неблокирующем стиле
Олег Мифле (Altenar) объяснит, зачем в PHP мьютексы
Алексей Солодкий (BelkaCar) поможет оптимизировать воркеры
Павел Иванов (HappyJob) обезопасит ваши Docker-образы
Александр Чередников (QTIM) построит для вас RAG-систему на PHP
Илья Рупасов (Битрикс) препарирует фреймворки тестирования
Переходите на сайт конференции и успейте купить билет по выгодным ценам.
Плагин Laravel Idea доступен бесплатно в PhpStorm
Адель Файзрахманов и Роман Пронский презентовали на Laracon 2025, что Laravel Idea теперь доступен для всех пользователей PhpStorm бесплатно!
RFC Updates
Большинство новостей ядра PHP подробно освещаются в серии PHP Core Roundup от PHP Foundation, мы лишь быстро по ним пробежимся:
❌ RFC: Single-Expression functions
Дмитрий Дерепко предложил синтаксис для объявления функций и методов с одним выражением в теле. Новый синтаксис упрощает написание лаконичных функций, улучшая читаемость и сокращая объем кода.
Предложение было отклонено.
✅ RFC: #[\DelayedTargetValidation] attribute
Daniel Scherzer предложил добавить атрибут #[\DelayedTargetValidation]
, который откладывает проверку допустимости целей атрибута до момента его использования, а не во время загрузки класса, что позволит писать более гибкие и переиспользуемые атрибуты, особенно в случаях, когда логика применения атрибута зависит от контекста, известного только во время выполнения.
Предложение было принято, новый атрибут появится в PHP 8.5.
❌ RFC: str_icontains
В PHP 8.0 появилась функция str_contains()
, которая обеспечивает ясный и лаконичный способ определения, содержит ли строка заданную подстроку.
Adam Cable предложил добавить функцию str_icontains()
, которая будет выполнять такую же проверку, но без учета регистра.
Предложение было отклонено.
? RFC: Readonly hooks
Larry Garfield и Nick Sdot предложили добавить реализацию хуков для свойств, доступных только для чтения, поскольку поддержка readonly-свойств была исключена из исходного RFC, в первую очередь для минимизации сложности.
Так как readonly-свойства предполагают неизменяемость и идемпотентность значения, а в хуке get можно повлиять на значение, голосование было разделено на 2 независимых части: добавить поддержку хука get для свойств, доступных только для чтения, и такое же голосование для хука set.
? RFC: Add locale for case insensitive grapheme functions
Функции для работы графемами не зависят от локали. Yuya Hamada предлагает добавить параметр локали для следующих функций: grapheme_strpos()
, grapheme_stripos()
, grapheme_strrpos()
, grapheme_strripos()
, grapheme_strstr()
, grapheme_stristr()
и grapheme_levenshtein()
.
? RFC: Cookies Having Independent Partitioned State (CHIPS)
Файлы cookie с независимым разделенным состоянием (CHIPS) позволяют разработчикам размещать файлы cookie в разделенном хранилище с отдельными банками файлов cookie для каждого сайта верхнего уровня, что повышает конфиденциальность и безопасность пользователей.
CHIPS представляет новый атрибут файлов cookie Partitioned
для поддержки межсайтовых файлов cookie, которые разделены по контексту верхнего уровня.
Дмитрий Дерепко и Niels Dossche предлагают расширить функции setcookie()
и setrawcookie()
, сделать их способными принимать еще один параметр partitioned
для управления поведением CHIPS. Использование partitioned
без установки secure
приведет к ошибке ValueError
.
? RFC: TrueAsync engine API RFC
Дмитрий (Edmond Dantes) активно потрудился с core-разработчиками PHP и представляет движок TrueAsync.
API движка представляет собой подключаемую платформу для асинхронного программирования в PHP. Она позволяет модулям регистрировать свои собственные реализации планировщика, реактора и пула потоков, сохраняя при этом независимость движка Zend от любой конкретной библиотеки циклов событий.
Основная цель состоит в том, чтобы отделить основные функции PHP от любого конкретного асинхронного бэкэнда, чтобы можно было заменять альтернативные реализации без изменения движка.
Это фактически первый шаг к внедрению асинхронных возможностей пользовательского пространства в PHP, что потребует отдельного RFC.
Если вы хотите узнать больше об асинхронном PHP, приходите на Пых.Конф – Дмитрий расскажет зачем PHP конкурентность, и какие выгоды она несёт.
Обновления Laravel
1. Методы doesntStartWith() и doesntEndWith() для строк
Feature: doesntStartWith() and doesntEndWith() string methods
PR #56168 от @balboacodes
Добавлены новые методы для работы со строками, которые дополняют существующий doesntContain()
. Проверяют, что строка НЕ начинается или НЕ заканчивается указанным значением.
Примеры использования:
use Illuminate\Support\Str;
// Вместо громоздкого !Str::startsWith()
$isValid = Str::doesntStartWith('Laravel Framework', 'PHP'); // true
$isValid = Str::doesntEndWith('Laravel Framework', 'Django'); // true
// С fluent строками
$filename = str('document.pdf');
$isNotTemp = $filename->doesntStartWith('temp_'); // true
$isValidType = $filename->doesntEndWith(['.exe', '.bat']); // true
// Валидация файлов
if (str($uploadedFile->name)->doesntEndWith(['.jpg', '.png'])) {
throw new InvalidFileTypeException('Only images allowed');
}
2. Метод failWhen() для ThrottlesExceptions middleware
Add failWhen method to ThrottlesExceptions job middleware
PR #56180 от @michaeldzjap
Добавляет возможность помечать задачи как failed вместо их удаления при определенных исключениях. Позволяет гибко управлять поведением задач при ошибках, особенно важно для цепочек задач.
use Illuminate\Queue\Middleware\ThrottlesExceptions;
use App\Exceptions\CriticalPaymentException;
class ProcessPayment implements ShouldQueue
{
public function middleware()
{
return [
(new ThrottlesExceptions(5, 60))
->failWhen(function ($exception) {
// Критические ошибки прерывают цепочку задач
return $exception instanceof CriticalPaymentException;
})
->deleteWhen(function ($exception) {
// Временные ошибки просто удаляем
return $exception instanceof NetworkTimeoutException;
})
];
}
}
3. Blade директива @context
[12.x] Add @context Blade directive
PR #56146 от @martinbean
Новая директива для работы с системой контекста Laravel в шаблонах Blade. Позволяет проверять наличие значений в контексте и выводить их, аналогично директиве @session
.
Примеры использования:
// В контроллере
context(['canonical' => 'https://example.com/page']);
// В Blade шаблоне
@context('canonical')
<link href="{{ $value }}" rel="canonical">
@endcontext
@context('meta_description')
<meta name="description" content="{{ $value }}">
@endcontext
// Уведомления
@context('success_message')
<div class="alert alert-success">{{ $value }}</div>
@endcontext
Важно знать! Может конфликтовать с JSON-LD схемами, используйте
@verbatim
или генерируйте JSON через PHP.
4. Атрибуты #[Singleton] и #[Scoped] для контейнера
[12.x] Add Singleton and Scoped attributes to Container
PR #56334 от @riasvdv
Декларативное управление жизненным циклом объектов в контейнере зависимостей. Позволяют указать способ создания экземпляров классов прямо в коде класса.
Примеры использования:
use Illuminate\Container\Attributes\Singleton;
use Illuminate\Container\Attributes\Scoped;
// Один экземпляр на все приложение
#[Singleton]
class ConfigurationManager
{
private array $cache = [];
public function get(string $key): mixed
{
return $this->cache[$key] ??= $this->loadFromFile($key);
}
}
// Один экземпляр на HTTP-запрос
#[Scoped]
class RequestContext
{
public function __construct(private Request $request) {}
public function getUserId(): ?int
{
return $this->request->user()?->id;
}
}
5. Методы whereValueBetween() для Query Builder
[12.x] Adds checking if a value is between two columns
PR #56119 от @DarkGhostHunter
Проверка того, находится ли значение между двумя колонками базы данных. Заменяют небезопасные raw-запросы и громоздкие конструкции с несколькими WHERE.
Примеры использования:
use App\Models\Post;
// Вместо небезопасного raw-запроса
// Post::whereRaw('? between "visible_from" and "visible_to"', [now()])
// Теперь безопасно и элегантно
$visiblePosts = Post::whereValueBetween(now(), ['visible_from', 'visible_to'])->get();
// Товары в ценовом диапазоне
$affordableProducts = Product::whereValueBetween($budget, ['min_price', 'max_price'])->get();
// Отрицание
$outsideRange = Model::whereValueNotBetween($value, ['min_col', 'max_col'])->get();
// С OR
$combined = Model::whereValueBetween($value1, ['col1', 'col2'])
->orWhereValueBetween($value2, ['col3', 'col4'])
->get();
6. Строгая числовая валидация numeric:strict
[12.x] Allows for strict numeric validation #56328
PR #56328 от @peterfox
Валидация, которая принимает только числовые типы данных, отклоняя строки. Обеспечивает типобезопасность для API, различая числа и их строковые представления.
Примеры использования:
// API валидация
$request->validate([
'price' => 'required|numeric:strict|min:0',
'quantity' => 'required|integer|numeric:strict',
]);
// Обычная валидация принимает '100' (string)
// Строгая валидация принимает только 100 (number)
// Примеры поведения
$validator = Validator::make(['value' => 100], ['value' => 'numeric:strict']); // PASS
$validator = Validator::make(['value' => '100'], ['value' => 'numeric:strict']); // FAIL
// Комбинирование правил
$rules = [
'user_id' => ['required', 'integer', 'numeric:strict', 'exists:users,id'],
'coordinates.x' => ['required', 'numeric:strict'],
'coordinates.y' => ['required', 'numeric:strict'],
];
Видео версия дайджеста: