У Laravel 12.54.0 з’явився Model::withoutRelation() — метод для вибіркового видалення зв’язків із клонованої моделі

Перекладено ШІ 0 Laravel News 12 березня, 2026

Laravel v12.54.0 додає Model::withoutRelation() для клонування моделей без конкретних відносин, метод interval() для зручного парсингу тривалостей і композитний індекс для покращення продуктивності черг. Хочете дізнатися, як ці зміни спростять роботу з моделями, запитами й тестами — читайте статтю.

Laravel v12.54.0 додає Model::withoutRelation() для вибіркового видалення зв’язків у клонованому екземплярі моделі, вводить interval() в InteractsWithData для парсингу значень тривалості та додає композитний індекс у таблицю jobs для прискорення опитування черги.

Основні нововведення:

  • Model::withoutRelation() — вибірково видаляє завантажені зв’язки без зміни оригіналу
  • interval() у InteractsWithData — перетворення даних запиту в CarbonInterval
  • Контекст запиту (метод, URL, статус) додається у вивід Response::dump() HTTP-клієнта
  • Підтримка BinaryFileResponse у тестах HTTP для асерту на стрімінг контенту
  • queue:monitor показує найстарішу очікувану задачу в текстовому виводі
  • Користувацькі розширення CommonMark для рендерингу Markdown у mail
  • Композитний індекс у таблиці jobs для кращої продуктивності опитування черги
  • Підтримка типу колонки tsvector у схемі для PostgreSQL

Що нового

Model::withoutRelation()

Model::withoutRelation() створює клон моделі з видаленими вказаними зв’язками, не змінюючи оригінал. Це проміжний варіант між withoutRelations() — яке прибирає всі зв’язки — та unsetRelation(), яке мутує модель на місці.

// Remove a single relation from a clone
$lightweight = $post->withoutRelation('comments');
 
// Remove multiple relations
$lightweight = $post->withoutRelation(['comments', 'tags']);
 
// Original is untouched
$post->relationLoaded('comments'); // true

Зручно для уникнення циклічних посилань, зменшення розміру payload у queued jobs та підготовки моделей до серіалізації, не видаляючи всі eager-loaded дані.

Pull Request: #59137

interval() у InteractsWithData

Новий метод interval() у InteractsWithData перетворює вхідні значення запиту в екземпляр CarbonInterval. Він приймає рядки ISO 8601, або числові значення з вказаною одиницею.

// ISO 8601 duration string ("P1DT2H" → 1 day, 2 hours)
$request->interval('duration');
 
// Numeric value with a string unit
$request->interval('timeout', 'second');  // "90" → 90 seconds
$request->interval('cooldown', 'day');    // "7"  → 7 days
 
// Or using the Carbon\Unit enum
$request->interval('delay', Unit::Minute);

Тепер, поряд із date(), форми мають нативний спосіб працювати з полями тривалості.

Pull Request: #59114

Контекст запиту у Response::dump()

Response::dump() HTTP-клієнта тепер показує метод запиту, URL і код статусу разом з тілом відповіді. Раніше виводилося лише тіло, що ускладнювало ідентифікацію відповіді при ланцюжку запитів.

// Before
{"error": {"message": "Invalid card"}}
 
// After
"POST https://api.stripe.com/v1/charges" 422
{"error": {"message": "Invalid card"}}

Pull Request: #59136

Підтримка BinaryFileResponse в асертах

Тестові відповіді від response()->file() і response()->download() тепер підтримують асерти на стрімінг контенту. Раніше assertStreamedContent() на BinaryFileResponse падало, бо тестовий response не міг прочитати файл.

$this->get('/download/report.pdf')
    ->assertOk()
    ->assertStreamedContent(file_get_contents('report.pdf'));

Pull Request: #59018

queue:monitor показує найстарішу очікувану задачу

Команда queue:monitor тепер виводить в стандартний текстовий потік вік найстарішої pending job. Раніше ця інформація була доступна лише в JSON-виводі.

Pending jobs ...................................... 3
Delayed jobs ...................................... 0
Reserved jobs ..................................... 1
Oldest pending job ................................ 2 minutes ago

Pull Request: #59073

Користувацькі розширення Markdown для Mail

Рендеринг Markdown у mail тепер дозволяє додавати власні CommonMark-розширення через конфіг mail.markdown.extensions. Раніше завантажувалися лише Core і Table extensions.

// config/mail.php
'markdown' => [
    'extensions' => [
        League\CommonMark\Extension\Strikethrough\StrikethroughExtension::class,
        League\CommonMark\Extension\TaskList\TaskListExtension::class,
    ],
],

Тут можна реєструвати будь-яке розширення, що реалізує CommonMark ExtensionInterface.

Pull Request: #59051

Композитний індекс у таблиці jobs

Міграція таблиці jobs тепер створює композитний індекс на (queue, reserved_at, available_at) замість індексу лише на queue. На навантажених чергах попередній одно-колонковий індекс змушував БД сканувати рядки, фільтруючи по reserved_at та available_at під час кожного опитування. Новий індекс відповідає формі запиту для опитування черги.

Це нова міграція й діє лише для чистих інсталяцій або додатків, що повторно запускають міграції. Існуючим проєктам слід додати індекс вручну за потреби.

Pull Request: #59111

Тип колонки tsvector для PostgreSQL

Schema builder тепер підтримує тип колонки tsvector для PostgreSQL, тож більше не потрібно використовувати raw SQL при визначенні колонок для повнотекстового пошуку.

Schema::table('articles', function (Blueprint $table) {
    $table->tsvector('search_vector')->nullable()->storedAs(
        "setweight(to_tsvector('english', coalesce(title, '')), 'A') || " .
        "setweight(to_tsvector('english', coalesce(body, '')), 'B')"
    );
});

Pull Request: #59004

Виправлення помилок і покращення

Queue & Jobs:

  • Запобігання deadlock у черзі, коли при резервуванні job кидається виключення (наприклад, overflow) (#58978)
  • Виправлено ділення на нуль у repeatEvery() (#58987)

Database:

  • Виправлено помилку migrate:fresh, коли база даних не існує (#59113)
  • Виправлено відображення enum у повідомленнях про помилку ModelNotFoundException (#59132)

HTTP & Filesystem:

  • Виправлено валідацію URL для punycode-піддоменів (#58982)
  • Підавлення помилок chmod у Filesystem::replace() на файлових системах без POSIX (#59126)
  • Виправлено права файлу кешу фасадів (#59059)

Console & Views:

  • Дедуплікація шляхів у view:cache (#59145)
  • Виправлено обрізання фінальних знаків пунктуації у TwoColumnDetail для значень другої колонки (#59010)
  • Дозволено, щоб app.editor.base_path був порожнім рядком (#58991)

Інше:

  • Виправлено ігнорування Redis throttle для after callbacks (#58990)
  • Виправлено after-commit observers, які ламали скасування подій з -ing (#59058)
  • Виправлено попередження про застаріле використання зсуву масиву (#59019)
  • Оновлено обмеження версії CommonMark, щоб усунути проблему безпеки DisallowedRawHtmlRenderer (#59131)

Посилання

Популярні

Інше, що варто прочитати

11 Оновлено 01 червня, 2026

Управління доступом у Filament за допомогою плагіна Shield

Дізнайтеся, як пакет Filament Shield забезпечує управління доступом до ваших панелей, ресурсів і віджетів у Laravel. Ця стаття розкриває основні можливості пакету, включаючи просту установку та підтримку багатокористувацьких середовищ — не пропустіть!

17 Оновлено 01 червня, 2026

Обробка геопросторових даних за допомогою Laravel Magellan

Ви готові відкрити нові горизонти у роботі з геопросторовими даними в Laravel? Дізнайтеся, як за допомогою PostGIS та пакету Laravel-Magellan можна легко зберігати, запитувати та маніпулювати інформацією про розташування, перетворюючи ваші проекти на вражаючі рішення у сфері картографії та геолокації!

30 Оновлено 01 червня, 2026

Інтеграція Laravel Socialite з бібліотекою Google Client PHP

Ви хочете навчитися, як інтегрувати Google OAuth у вашому проекті Laravel, використовуючи Socialite? Дізнайтеся, як налаштувати доступ до сервісів Google, таких як Календар, у нашій сьогоднішній статті