Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама
Новини 27 серпня 2026

Laravel 13.27: маскування параметрів запитів, бінарні порівняння та пасимістичні блокування

Laravel 13.27 додає опцію для кожного з'єднання, яка виключає параметри запитів з повідомлень про помилки, сімейство методів whereBinary() для побайтових порівнянь на MySQL та MariaDB, метод refreshForUpdate() для перезавантаження Eloquent-моделі під песимістичним блокуванням та багато іншого.

Маскування параметрів запитів у повідомленнях про помилки

QueryException інтерполює параметри у своє повідомлення, тому невдалий INSERT додає кожне значення параметра в getMessage(). Це повідомлення потім потрапляє всюди, куди потрапляють винятки: таблиця failed_jobs, лог-файли та APM-траси. Адреси електронної пошти, імена тощо логуються.

Новий ключ конфігурації для кожного з'єднання зупиняє інтерполяцію і залишає плейсхолдери ? на місці:

'mysql' => [
    'driver' => 'mysql',
    // ...
    'mask_bindings_in_exception_messages' => env('DB_MASK_BINDINGS', false),
],
// за замовчуванням
SQLSTATE[23000]: ... SQL: insert into `users` (`email`) values (foo@example.com))
// замасковано
SQLSTATE[23000]: ... SQL: insert into `users` (`email`) values (?))

Ключ присутній у власному config/database.php фреймворку, тому додатки, які ніколи не публікували цей файл, можуть увімкнути його лише через DB_MASK_BINDINGS=true. За замовчуванням встановлено false, і змінюється лише повідомлення; getBindings() все ще повертає значення.

whereBinary() для регістрозалежних порівнянь

Стандартні колації MySQL порівнюють без урахування регістру, тому where('name', 'John') також збігається з john та JOHN. Отримання точного побайтового порівняння означало використання сирого SQL:

DB::table('queues')->whereRaw('name = BINARY ?', [$queueName])->first();

whereBinary() робить те саме через конструктор запитів, разом з orWhereBinary(), whereNotBinary() та orWhereNotBinary():

DB::table('queues')->whereBinary('name', $queueName)->first();
// select * from `queues` where `name` = binary ?
DB::table('queues')->whereNotBinary('name', $queueName)->get();
// select * from `queues` where `name` != binary ?

MariaDB успадковує граматику MySQL, тому це працює і там. Postgres, SQLite та SQL Server викидають RuntimeException, відповідно до того, як whereLike() обробляє регістрозалежний пошук на движках, які вже порівнюють з урахуванням регістру.

refreshForUpdate()

Моделі зазвичай резолвляться до початку транзакції через прив'язку моделі до маршруту або payload завдання. Встановлення песимістичного блокування означало викидання цього екземпляра і повторний запит за первинним ключем:

DB::transaction(function () use ($product) {
    $product = Product::query()
        ->lockForUpdate()
        ->findOrFail($product->getKey());
    $product->decrement('stock');
});

refreshForUpdate() поводиться як refresh() з lockForUpdate(), застосованим до запиту перезавантаження, тому екземпляр, який у вас уже є, оновлюється на місці і залишається придатним для використання протягом решти транзакції:

DB::transaction(function () use ($product) {
    $product->refreshForUpdate();
    if ($product->stock === 0) {
        throw new RuntimeException('The product is out of stock.');
    }
    $product->decrement('stock');
});

Блокування діє лише протягом життя транзакції, тому виклик належить всередині неї; це закриває гонку даних між читанням моделі та записом назад.

Фасад Cloud

Відповідь на питання "чи ми на Laravel Cloud і чи використовуємо керовані черги?" раніше означала поєднання хелпера laravel_cloud() з перевірками драйвера. Фасад Cloud збирає це в три методи:

use Illuminate\Support\Facades\Cloud;

Cloud::hosted();            // працює на Laravel Cloud?
Cloud::usesManagedQueues(); // чи налаштовано cloud queue з'єднання?
Cloud::queue();             // саме керована черга

Cloud::queue() викидає RuntimeException, коли керовані черги не налаштовані, тому він працює в парі з usesManagedQueues(), а не замінює його. Фасад не зареєстрований у стандартних псевдонімах, тому він не конфліктуватиме з існуючим класом Cloud у додатку.

Загальні метрики черг

Існуючі методи pendingSize(), delayedSize() та reservedSize() приймають одну назву черги, тому панель керування, що охоплює кілька черг, мала підсумовувати їх вручну. Три total аналоги роблять це за один виклик:

Queue::totalPendingSize();
Queue::totalDelayedSize();
Queue::totalReservedSize();

Вони підсумовують по всіх чергах, про які знає з'єднання, і на відміну від методів allXJobs() вони лише рахують, тому жодні payload завдань не декодуються. Реалізовано для Redis, database, failover та fake драйверів.

Векторні запити відстаней на MariaDB

Раніше whereVectorSimilarTo(), whereVectorDistanceLessThan(), orderByVectorDistance() та selectVectorDistance() працювали лише на Postgres. Обидва перемістилися в граматику, слідуючи патерну, який вже використовується для compileRandom() та supportsSavepoints(). MariaDB 11.7+ має нативний тип колонки VECTOR та функції відстаней, тому його граматика компілюється в vec_distance_cosine(), а підтримка typeVector() зі сторони схеми нарешті має відповідну сторону запитів. Звичайний MySQL все ще викидає помилку, оскільки VECTOR_DISTANCE() існує лише на MySQL HeatWave.

Посилення обробки вводу та валідації

Контрибутор @KIKOmanasijev додав кілька виправлень щодо того, як Laravel читає ключі та порівнює значення.

Request::merge(['*' => 226]) раніше стирав весь масив вводу замість додавання ключа *, оскільки редуктор прогонював ключі через data_set(), який трактує * як підстановочний знак. Uri::withQuery() мав ту саму помилку на рівень вище. Обидва тепер використовують Arr::set(), який зберігає нотацію з крапкою для справжніх вкладених злиттів, але зберігає * буквально.

Відхилення невідомих полів, додане в Laravel 13, згладжувало введення з Arr::dot(), що створює той самий ключ для вкладеного поля profile[name] і буквального ключа "profile.name". Валідатор екранує буквальні крапки як profile\.name, тому ці два порівнювали ключі в різних нотаціях. Ключі вводу тепер згладжуються з тим самим екрануванням, яке використовують ключі правил.

Два правила валідації все ще використовували нестрогі порівняння. in_array збігав "1e0" з "1" та "0e123456789" з "0", а doesnt_contain провалював масив, що містить "0e123", наче він містив заборонений "0". Обидва тепер використовують строге порівняння, слідуючи тому ж виправленню, застосованому до правила in раніше.

Нарешті, MaintenanceModeBypassCookie::isValid() перевіряв, що mac cookie встановлено, але не те, що це рядок, тому cookie laravel_maintenance, що несе масив, передавав цей масив у hash_equals() і перетворював очікуваний 503 у неавтентифікований 500. Перевірка isset() стала is_string().

Інші виправлення та покращення

  • Postgres-з'єднання приймають ключі конфігурації keepalives, keepalives_idle, keepalives_interval та keepalives_count, які досягають DSN замість того, щоб бути відкинутими, тому довгоживуче з'єднання worker не вбивається мовчки тайм-аутом простою файрволу
  • SQS-з'єднання можуть ділитися кешованими AWS-облікаими даними між процесами через опцію credentials_cache, замінюючи одне отримання облікових даних на PHP-FPM worker одним на ротацію. Laravel Cloud вмикає це за замовчуванням для керованих черг
  • orWhereKey() та orWhereKeyNot() повернулися. Перша спроба була в 13.26 і була відкликана в 13.26.1 через зміну сигнатур whereKey(), що фатально зламало підкласи Builder, які їх перевизначають. Ця версія делегує через вкладену where-групу і залишає існуючі методи недоторканими
  • move() та copy() на read-through диску тепер стримлять з fallback, коли primary ще не просунув файл, замість повернення false для файлу, про який exists() повідомляє як про присутній
  • Debounced завдання більше не залишає свою мітку часу maxWait після виконання, що змушувало перший dispatch наступного burst повністю пропускати debounce
  • Queued завдання, відправлене всередині транзакції, більше не примусово звільняє унікальне блокування, яке воно ніколи не набувало, коли транзакція відкочується
  • Замикання обмежень eager-load знову static, розриваючи цикл посилання Builder, який зберігав builders та їхні завантажені дерева відносин живими до запуску збирача циклів, що найбільше важить у queue workers та Octane
  • Process::quietly()->run(...)->throw() викидає ProcessFailedException, а не LogicException про вимкнений вивід, а FakeInvokedProcess отримав stop() та ensureNotTimedOut(), щоб фейкові процеси можна було зупиняти в тестах
  • InteractsWithTestCaseLifecycle::flushState() надає додаткам задокументований хук для очищення власного статичного стану між тестами замість перевизначення внутрішнього tearDownTheTestEnvironment()
  • Зображення, створені зі stream, більше не провалюються при другому читанні, оскільки lazy loader тепер резолвиться один раз і ділиться результатом з клонами. fromUrl() перестає робити свіжий HTTP-запит на читання з тієї ж причини, і fromUrl() викидає помилку при неуспішних відповідях замість трактування тіла 404 як даних зображення
  • PhpRedisConnection::mget() та hmget() захищаються від false, яке phpredis повертає при відхиленій команді, що виявлялося як TypeError від array_map() при CROSSSLOT помилці
  • Виняток Brick\Math більше не уникає правил числового порівняння. Охоронці gt та gte ловили неправильний клас MathException, а lt та lte взагалі не мали охоронця
  • Container::scoped() більше не записує той самий abstract двічі в $scopedInstances, Route::name('x')->post(...) зберігає своє ім'я для дій контролера масиву, а maxRelationshipDepth(0) скидає вкладені includes замість взяття сегментів з кінця масиву
4

Читати в документації

Коментарі

Увійдіть, щоб залишити коментар

Будьте першим, хто залишить коментар!

Читайте також

Filament v5.10.0
Новини 12 жовтня 2026

Filament v5.10.0: сітка в rich editor, скелетони таблиць і десятки виправлень

Вийшов Filament v5.10.0: елементи керування сіткою в rich editor, допоміжний контент для віджетів-графіків, скелетони завантаження таблиць, submitOnCompletion() для OneTimeCodeInput та багато виправлень авторизації, доступності й стану.

22
Laravel AI SDK на практиці
Новини 09 жовтня 2026

Laravel AI SDK на практиці: агент, що стоїть за There There

Фрік Ван дер Гертен розповідає, як у Spatie побудували AI-шар хелпдеска There There на Laravel AI SDK: клас агента, інструменти з типізованою JSON-схемою та делегування роботи звичайним domain-діям.

18

Вакансії за темою

Yalantis Нова
2 дні тому

WordPress/PHP Developer

Розробник буде працювати над внутрішніми рішеннями продуктової команди, які впливають на процеси та ефективність компанії. Основний стек: WordPress і PHP, додатково JavaScript (ES6, TypeScript), MariaDB, Redis та AWS. Потрібен досвід комерційної розробки на WordPress/PHP від 3 років, знання роботи з API та веб-сервісами, розуміння ООП та Agile/Scrum.

Hamsters.pro Нова
2 дні тому

PHP Tech Lead / Software Architect (hands-on)

Технічний лідер, який прийме чинні PHP-системи (CPA-платформа, CRM/ERP, інструменти Media Buying) і організує роботу невеликої команди, самостійно беручи участь у розробці. Головний стек: PHP 7.4-8.5 на власному framework, прямий SQL до MariaDB, Redis, Memcached, Node.js/WebSocket. Потрібен досвід 5+ років комерційного PHP, роботи з legacy-кодом, фінансово значущих операцій, інтеграцій із ідемпотентністю та поступової модернізації з міграцією даних. Також потрібні базові DevOps-навички в Linux,

HAMSTERS Нова
2 дні тому

Middle PHP Developer (CRM / CPA / Integrations)

Самостійний PHP-розробник для доопрацювання чинних продуктів CRM, CPA-платформи та інтеграцій з рекламодавцями, fulfillment-партнерами й службами доставки. Працюватимеш з Tech Lead над обробкою статусів, webhooks і фоновими задачами, писатимеш тести та брати участь у поетапній міграції на нові версії PHP. Стек: PHP 7.4-8.5, власний модульний фреймворк, MariaDB з прямим SQL, Redis, Memcached, JavaScript/jQuery. Потрібен досвід від 3 років на PHP, робота з legacy-кодом, впевнений SQL, досвід REST

Пакети за темою

Laravel Query Builder

spatie/laravel-query-builder

Легко будуйте Eloquent-запити на основі запитів від API.

4,470 7.3.6 13 11

Laravel Medialibrary

spatie/laravel-medialibrary

Пакет для асоціювання файлів з Eloquent-моделями. Надає зручний інтерфейс для управління медіа-файлами, пов'язаними з вашими моделями бази даних.

6,168 11.23.10 13 8