Всем привет!

Это 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'],
];

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

Комментарии (0)