Laravel 13.2.0 додає набір нових симетричних, виразних PHP-атрибутів для Eloquent-моделей, підтримку enum у #[Queue] та #[Connection], і не тільки.
Головні нововведення:
- Нові симетричні атрибути для Eloquent-моделей (
#[DateFormat],#[WithoutTimestamps]та ін.) - Підтримка enum у атрибутах черги
#[Queue]і#[Connection] - Параметр
releaseOnSignalдляwithoutOverlapping()— обробка раптового завершення процесу UniqueConstraintViolationExceptionтепер містить інформацію про колонки та індексschedule:listвідображає cron-вирази в правильному часовому поясі
# Що нового
# Симетричні атрибути Eloquent-моделей
PR #59284 додає набір вузькоспрямованих, однозавданих атрибутів як альтернативу багатопараметровим атрибутам на кшталт #[Table]. Замість того, щоб поєднувати кілька налаштувань в одному атрибуті, кожне налаштування тепер має власний атрибут:
// Before
#[Table(timestamps: false, dateFormat: 'U')]
class Post extends Model {}
// After
#[DateFormat('U')]
#[WithoutTimestamps]
class Post extends Model {}
Нові атрибути відображають властивості, які вже є в Eloquent-моделях, що спрощує декларативну конфігурацію поведінки моделі на рівні класу.
Pull Request: #59284
# Підтримка enum у #[Queue] та #[Connection]
Атрибути PHP #[Queue] і #[Connection] тепер приймають backed enums безпосередньо, тож можна передавати case enum без виклику ->value:
// Before
#[Queue(Queues::LOGS_INGESTION->value)]
final class IngestAuditLog implements ShouldQueue {}
// After
#[Queue(Queues::LOGS_INGESTION)]
final class IngestAuditLog implements ShouldQueue {}
Це узгоджує поведінку атрибутів з тим, що вже підтримувалося через властивість безпосередньо.
Pull Request: #59278
# releaseOnSignal для withoutOverlapping()
withoutOverlapping() тепер приймає параметр releaseOnSignal. Якщо встановити його в true, замок перекриття (збережений як ключ кешу) звільняється при отриманні процесом сигналу завершення (SIGTERM, SIGINT або SIGQUIT), тож завдання може запуститися знову відразу після перезапуску планувальника.
Без цього, якщо процес планувальника вбити під час виконання завдання — що може трапитись на керованій інфраструктурі — замок лишиться встановленим і завдання не виконається знову, поки не сплине TTL замка.
Artisan::command('reports:generate', function () {
// ...
})->withoutOverlapping(releaseOnSignal: true);
Потрібне розширення pcntl.
Pull Request: #59298
# UniqueConstraintViolationException містить дані про колонки та індекс
UniqueConstraintViolationException тепер відкриває доступ до колонок і назви індексу, що брали участь у порушенні унікальності. Наявність даних залежить від драйвера БД:
| Driver | columns |
index |
|---|---|---|
| SQLite | ✅ | ❌ |
| PostgreSQL | ✅ | ✅ |
| MySQL | ❌ | ✅ |
| SQL Server | ❌ | ✅ |
try {
User::create(['email' => 'taken@example.com']);
} catch (UniqueConstraintViolationException $e) {
$e->columns; // e.g. ['email'] on PostgreSQL/SQLite
$e->index; // e.g. 'users_email_unique' on PostgreSQL/MySQL/SQL Server
}
Pull Request: #59299
# schedule:list відображає вирази в правильному часовому поясі
Команда schedule:list тепер показує cron-вирази, приведені до часового поясу, налаштованого для кожного завдання, замість того, щоб завжди відображати їх у часовому поясі додатка. Це робить вивід відповідним до реального часу виконання завдання.
Pull Request: #59286
# Атрибут Backoff тепер варіативний
Атрибут #[Backoff] тепер приймає варіативний перелік значень затримки, що відповідає підходу з масивом, доступному через властивість backoff у queued jobs:
#[Backoff(10, 30, 60)]
class ProcessOrder implements ShouldQueue {}
Pull Request: #59354
# Магічні factory-методи приймають кілька масивів
Динамічні factory-методи has*() (наприклад, hasPosts(), hasTags()) тепер приймають кілька масивів, тож можна передавати різні набори атрибутів для кожної пов’язаної моделі без ручного використання forEachSequence():
User::factory()
->hasPosts(['title' => 'First Post'], ['title' => 'Second Post'])
->create();
Внутрішньо передача кількох масивів викликає forEachSequence(), створюючи по одній пов’язаній моделі на кожен масив з відповідними атрибутами.
Pull Request: #59343
# Інші виправлення й покращення
Queue & Workers:
- Додано причину зупинки worker —
TimedOut(#59310) - Додана можливість відключити звітування про виключення job у worker (#59308)
- Прив’язали слухача запитів для сторінки помилок, щоб запобігти росту використання пам’яті в Octane (#59309)
Models & Database:
- Виправлено некоректне інкрементування атрибуту
Tableдля Pivot-моделей (#59336) - Забезпечено роботу атрибута
ScopedByз наслідуванням (#59332) - Дозволено передавати enum в атрибути моделей (#59297)
- Забезпечено роботу
connectUsing()зUnitEnum(#59306)
Collections:
- Колбек для
sum()тепер отримує ключ елемента як другий аргумент (#59322)
HTTP & Streaming:
- Обробка виключень у
eventStream(), щоб уникнути фатальних помилок (#59292) - Виправлено сигнатуру
LazyPromise::wait()для сумісності зPromiseInterfaceвід Guzzle (#59301)
Testing:
- Виправлено відсутню інверсію для асерта
assertDontSeeInHtml()(#59303)
Error Page:
- Додано підтримку mobile safe-area-inset у рендері виключень (#59341)
Performance:
- Покращено продуктивність підстановки raw SQL-біндінгів (#59277)