Дата випуску: 10 лютого 2026
Версія Laravel: 12.51.0
Короткий огляд
Laravel v12.51.0 додає колбеки afterSending() у Notification, флюентні методи whenFails() та whenPasses() у Validator, метод timeout() для MySQL query builder, а також підтримку замикань у firstOrCreate і createOrFirst для лінивої оцінки значень. У релізі з'явився подія BatchCancelled, підтримка Eloquent builder як підзапитів в update-запитах і метод withoutHeader() у Response.
Головні нововведення:
- Колбеки
afterSending()у Notification - Методи
whenFails()іwhenPasses()у Validator - Метод
timeout()у MySQL query builder - Підтримка замикань у
firstOrCreate/createOrFirst - Подія
BatchCancelled - Eloquent builders як підзапити в update-запитах
withoutHeader()у Response- Покращення тестування батчів та ізоляція кешу для паралельних тестів
- Безліч виправлень багів та покращень типізації
Що нового
Notification — виклики afterSending()
Класи Notification тепер можуть визначати метод afterSending, який виконується після відправлення сповіщення на кожному каналі. Це зручний спосіб виконувати логіку після відправлення — наприклад оновити модель або кинути подію — без реєстрації окремого слухача NotificationSent:
class BookingNotification extends Notification
{
public function __construct(public Booking $booking) {}
public function via(): array
{
return ['mail'];
}
public function toMail(): MailMessage
{
// ...
}
public function afterSending($notifiable, $channel, $response)
{
$this->booking->update(['notified_at' => now()]);
}
}
Метод отримує інстанс notifiable, назву каналу та відповідь каналу — цього достатньо для подальших дій.
Pull Request: #58654
Validator — методи whenFails() та whenPasses()
Validator отримав флюентні методи whenFails() та whenPasses() для обробки результатів валідації. Це особливо корисно поза HTTP-циклoм — наприклад в Artisan-командах або queue job:
public function someMethod($file)
{
Validator::make(
['file' => $file],
['file' => 'required|image|dimensions:min_width=100,min_height=200']
)->whenFails(function () {
throw new InvalidArgumentException('Provided file is invalid');
});
}
Ці методи — альтернатива ручній перевірці $validator->fails() або обгортанню в try/catch.
Pull Request: #58655
MySQL query builder — метод timeout()
Додано метод timeout() у query builder, який встановлює таймаут виконання запиту для MySQL через optimizer hint MAX_EXECUTION_TIME:
Student::query()
->where('email', 'like', '%text%')
->timeout(60)
->get();
// Generates: select /*+ MAX_EXECUTION_TIME(60000) */ * from `students` where `email` like ?
Можна також застосувати його як дефолт через глобальний scope:
use Illuminate\Database\Eloquent\Attributes\ScopedBy;
class TimeoutScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder->timeout(60);
}
}
#[ScopedBy([TimeoutScope::class])]
class User extends Model
{
// ...
}
Функція специфічна для MySQL і приймає значення таймауту в секундах.
Pull Request: #58644
Замикання в firstOrCreate і createOrFirst
Методи firstOrCreate та createOrFirst тепер приймають closures для параметра $values, що дозволяє відкладено обчислювати дорогі операції:
// Before — expensive operation always runs
$location = Location::query()->firstWhere('address', $address);
if ($location) {
return $location;
}
return Location::create([
'address' => $address,
'coordinates' => Geocoder::resolve($address),
]);
// After — geocoding only runs when a new record is needed
$location = Location::firstOrCreate(
['address' => $address],
fn () => ['coordinates' => Geocoder::resolve($address)],
);
Якщо запис уже існує, замикання не виконується — це запобігає зайвим API-запитам чи обчисленням.
Pull Request: #58639
Подія BatchCancelled
Додано подію BatchCancelled, яка глобально спрацьовує при скасуванні батчу — автоматично через помилку в job або при ручному скасуванні. Це дає змогу відслідковувати скасування батчів без опитування:
use Illuminate\Bus\Events\BatchCancelled;
use Illuminate\Support\Facades\Event;
Event::listen(BatchCancelled::class, function (BatchCancelled $event) {
Log::warning("Batch {$event->batch->id} was cancelled.");
});
Pull Request: #58627
Eloquent builders як підзапити в update
Eloquent builders і relations тепер можна передавати напряму як підзапити в update-викликах без конвертації в base query:
// Before
FooModel::where('...')->update([
'bar_id' => BarModel::where('...')->toBase()->select('id'),
]);
// After
FooModel::where('...')->update([
'bar_id' => BarModel::where('...')->select('id'),
]);
Виклик ->toBase() більше не потрібен при використанні Eloquent builder як значення підзапиту.
Pull Request: #58692
withoutHeader() у Response
Додано метод withoutHeader() для видалення заголовків з HTTP-відповіді — симетрично до існуючого withoutCookie():
// Remove a single header
return response($content)->withoutHeader('X-Debug');
// Remove multiple headers
return response($content)->withoutHeader(['X-Debug', 'X-Powered-By', 'Server']);
Pull Request: #58671
Виправлення багів і покращення
Тестування:
assertJobsуPendingBatchFakeдля перевірок job у батчі (#58606)Bus::assertBatched()з підтримкою масивів (#58659)viewData()без ключа повертає всі дані view уTestResponse(#58700)- Ізоляція префікса кешу для паралельних тестів через трейд
TestCaches(#58691)
HTTP Client:
throwIfStatus/throwUnlessStatusтепер працюють для всіх статусів, включаючи 2xx і 3xx (#58724)
Database & Eloquent:
- Метод
orderByPivotDesc()для спадного сортування pivot-колонки (#58720) whereBetweenприймаєDatePeriodі коректно обробляє відсутні кінцеві дати (#58687)- Підтримка SSL cert/key для дампів та завантаження схем MySQL (#58690)
- Виправлення початкового значення sequence у Postgres для кастомних схем/з'єднань (#58199)
- Коригування
freshTimestampдля SQL Server (#58614) - Виправлення підрахунку батчів, коли
deleteWhenMissingModelsпропускає відсутні моделі (#58541)
Strings & Helpers:
Stringable::deduplicate()приймає масив символів (#58649)- Виправлено
Str::substrReplaceдля граничних випадків з від'ємним offset або length (#58634) - Виправлено
Str::isUrl(), яке повертало false для односимвольних доменів (#58686) - Заміна
substrнаmb_substrдля кодування user agent (#58703)
Queue & Middleware:
- Можливість вказати Redis-підключення в Redis-based queue middleware (#58656)
- Виправлено, що
Queue::fake()не звільняв унікальні блокування job між тестами (#58718)
Translation & Localization:
- Усунено дублювання перевірок локалі в
Lang::get(), коли локаль збігається з fallback (#58626) - Виправлено regex у
trans_choice, щоб дозволити від'ємні діапазони (#58648)
Framework & Internals:
- Відновлення оригінальних биндів dispatcher після precognitive request — фікс для Octane і Pest (#58716)
- Обробка бінарних даних у
Js::encode()debug renderer (#58618) - Додав ArrayObject props до
AsEncryptedArrayObjectщоб відповідатиAsArrayObject(#58619) - Виправлено поп-ін сторінки винятків для неосновних фреймів (#58698)
- Вирівнювання ASCII SVG символів Laravel (#58702, #58719)
- Додано депрекацію до
Request::get()(#58635) - Оновлено завдання reload для включення
schedule:interruption(#58637)