Laravel v12.53.0 introduces Cache::funnel() for concurrency limiting backed by any lock-capable cache driver, adds named argument support to event dispatching and broadcasting, and extends PostgreSQL full-text search with pre-computed tsvector column support.
Key highlights include:
Cache::funnel()for cache-backed concurrency limiting- Named arguments in event dispatching and broadcasting
whereFullTextvector option for pre-computed tsvector columns (PostgreSQL)buildMorphMapFromModels()accepts array keysphp artisan downcan refresh maintenance mode options in-place- Event macros on schedule groups
What's New
Cache::funnel() Concurrency Limiting
Cache::funnel() brings concurrency limiting to any cache driver that supports atomic locks — including the array, file, database, and Redis drivers. Previously, concurrency limiting in Laravel relied on Redis::funnel(), which required a Redis connection. This new facade method works across drivers using the same lock primitives already available in the cache layer.
Cache::funnel('payment-processing') ->limit(3) ->releaseAfter(60) ->then( fn() => processPayment(), fn() => 'Currently at capacity' );
limit(int $slots)— max concurrent operations allowedreleaseAfter(int $seconds)— how long to hold the lock before auto-releaseblock(int $timeout)— how long to wait for a slot before giving upthen(callable $success, callable $failure)— runs the success callback when a slot is acquired, or the failure callback when blocked
If the driver doesn't support locks, a BadMethodCallException is thrown. When a blocking timeout expires without a failure callback, a LimiterTimeoutException is raised.
Pull Request: #58439
Named Arguments in Event Dispatching and Broadcasting
The Dispatchable trait now supports named arguments when calling dispatch() and broadcast() on event classes. The trait previously used func_get_args() internally, which discarded argument names. Switching to variadic syntax allows named arguments to pass through to the event constructor.
// Before — positional arguments onlyevent(new UserSubscribed($user, $plan, $metadata)); // After — named arguments now workUserSubscribed::dispatch( user: $user, plan: $plan, metadata: ['source' => 'checkout'],);
This is consistent with how job dispatching already handles named arguments. Existing positional-argument calls continue to work without changes.
Pull Request: #58913
PostgreSQL Full-Text Search with Pre-Computed tsvector Columns
whereFullText() gains a vector option for PostgreSQL that treats the column as a pre-computed tsvector instead of wrapping it in to_tsvector() on every query. This is useful when you maintain a dedicated tsvector column — often indexed with GIN — to avoid the overhead of recomputing the vector at query time.
// Without vector option — wraps column in to_tsvector()$query->whereFullText('body', $term, ['language' => 'english']); // With vector option — uses the column directly$query->whereFullText('search_vector', $term, [ 'vector' => true, 'language' => 'english', 'mode' => 'websearch',]); // Also works with multiple tsvector columns$query->whereFullText(['tsv_title', 'tsv_body'], $term, ['vector' => true]);
Pull Request: #58893
buildMorphMapFromModels() Accepts Array Keys
buildMorphMapFromModels() now accepts any array key type — string or integer — when building a morph map from model classes. Previously the parameter only accepted list-style integer-keyed arrays, which prevented using custom string aliases:
// Custom string aliases now workRelation::buildMorphMapFromModels([ 'post' => Post::class, 'video' => Video::class,]);
Pull Request: #58891
Maintenance Mode down Refreshes Options In-Place
php artisan down can now be re-run while the application is already in maintenance mode to update options — such as the secret, message, or retry value — without taking the site back up first. Previously, you had to run php artisan up before changing maintenance mode settings.
# Put site in maintenance modephp artisan down --secret="my-secret" # Update the secret without bringing the site back upphp artisan down --secret="new-secret"
Pull Request: #58918
Event Macros on Schedule Groups
Scheduled command Event macros can now be applied to schedule groups, allowing shared behavior to be registered once and applied to all commands in a group rather than on each entry individually.
Pull Request: #58926
Bug Fixes and Improvements
Database:
- Fix cross-database null-safe equals operations (#58962)
- Rollback lingering PDO state before retrying on commit deadlock (#58906)
Queue & Jobs:
- Fix model serialization in queue jobs (#58939)
- Fix
RetryCommandnot working for SQS FIFO queues (#58936) - Ensure
oldest_pendingdisplays correctly inqueue:monitor(#58952)
HTTP & Caching:
- Fix race condition when creating real-time facade cache file (#58947)
- Fix
RequestExceptionsummarizing for Guzzle streamed responses (#58909) - Cache now supports serializable class values (#58911)
Testing:
- Show all mismatched values in
assertSessionHasAllfailure output (#58946)
Mail:
- Change text alignment from
lefttostartfor better RTL language support (#58935)