New updates and improvements to Laravel's open source products.
Pull request by @jackbayliss
Queue, bus, event, and notification fakes now accept an array of expected properties in their assertions, so tests can match a dispatched object without writing a callback. Values are compared strictly, while Eloquent models are matched using their is() method.
1use Illuminate\Support\Facades\Queue;2 3Queue::assertPushed(ProcessPodcast::class, [4 'podcast' => $podcast,5 'status' => 'pending',6]);
Pull request by @jackbayliss
The queue:work command now accepts a percentage of PHP's configured memory_limit for its --memory option. For example, php artisan queue:work --memory=60% lets a worker's memory threshold scale with its environment instead of requiring a fixed megabyte value.
Pull request by @Ashot1995
The response factory now has a markdown() method for returning Markdown with the text/markdown content type. For example, response()->markdown($post->markdown) accepts optional status and header arguments, making it useful alongside request methods such as wantsMarkdown() when serving multiple representations of a page.
Pull request by @jackbayliss
Schedule::alwaysOnOneServer() opts every eligible scheduled task into onOneServer() without wrapping all tasks in a group or remembering to mark each new one. This helps avoid duplicate execution when multiple servers run the scheduler. Unnamed scheduled closures are left unchanged because they cannot use onOneServer().
1use Illuminate\Support\Facades\Schedule;2 3Schedule::alwaysOnOneServer();
Pull request by @joelbutcher
Laravel now supports the HTTP QUERY method in routing, including Route::query(). Route::any() also matches QUERY requests, and the route list recognizes the expanded set of methods. Unlike ordinary reading methods, QUERY routes remain subject to CSRF verification in the web middleware group.
1use Illuminate\Support\Facades\Route;2 3Route::query('/products/search', SearchProductsController::class);
Pull request by @jackbayliss
MySQL connections now provide isVitess() to detect Vitess or PlanetScale and olap() to run a callback under Vitess's OLAP workload. The workload is set on both read and write connections and restored to OLTP afterward, even if the callback throws. On ordinary MySQL connections, the callback runs without changing the workload.
1use Illuminate\Support\Facades\DB;2 3$results = DB::connection()->olap(fn () => Order::query()4 ->where('created_at', '>=', now()->subYear())5 ->get());
Pull request by @ericmp33
Laravel now offers Rule builder methods for many validation rules that previously required string syntax, including requiredWith(), acceptedIf(), regex(), and timezone(). The methods make rules easier to discover through IDE completion while retaining their existing validation behavior.
1use Illuminate\Validation\Rule;2 3$rules = [4 'name' => [Rule::requiredWith('email'), Rule::regex('/^[A-Za-z ]+$/')],5];
Pull request by @jackbayliss
The opt-in PreventStaleDatabaseReads middleware uses the write connection for a user's reads shortly after that user writes to the default database connection. It records the write time in the session and returns reads to replicas after two seconds by default, avoiding stale data immediately after an update. The window can be changed with PreventStaleDatabaseReads::for(15).
1use Illuminate\Foundation\Http\Middleware\PreventStaleDatabaseReads;2 3$middleware->web(append: [PreventStaleDatabaseReads::class]);
Pull request by @jackbayliss
Connection::usingWritePdo() runs a callback with reads directed to the write connection, including queries made through related models on that connection. It restores the previous read preference afterward, even when the callback throws, so a critical read can avoid replica lag without changing later queries.
1use Illuminate\Support\Facades\DB;2 3$posts = DB::connection()->usingWritePdo(fn () => User::query()4 ->where('email', $email)5 ->first()6 ?->posts()7 ->get());
Products