Laravel 13.19.0 rounds out support for the HTTP QUERY method across the HTTP client and testing helpers, and adds a handful of collection, string, and queue improvements alongside the usual fixes.

  • Http::query() client method for sending QUERY requests
  • query() and queryJson() HTTP testing helpers
  • reduceInto() collection method for mutating an accumulator
  • counted() helper on Str and Stringable
  • Bulk SQS dispatch via SendMessageBatch, plus reserved-job inspection on the queue fake

What's New

Http::query() Client Method

The HTTP client gains a query() method for issuing requests with the HTTP QUERY verb, which carries its parameters in the request body rather than the URL. It mirrors the existing post(), put(), and patch() methods, sending JSON by default or form-encoded data when you call asForm().

$response = Http::query('https://api.example.com/search', [

'filter' => ['status' => 'active'],

]);

Existing URL query handling is unchanged: withQueryParameters() and the $query argument to get() continue to work as before. See #60663.

query() and queryJson() Testing Helpers

To match the client-side addition, the test suite gains query() and queryJson() helpers for exercising routes that respond to QUERY. They mirror verb-specific methods like delete() and deleteJson(), placing the test data in the request body.

Route::match(['QUERY'], '/search', fn () => request()->input('filter'));

$this->queryJson('/search', ['filter' => 'active'])->assertOk();

See #60662.

reduceInto() Collection Method

reduceInto() is a variant of reduce() for cases where you mutate an accumulator in place instead of returning a new value each iteration. The callback receives the accumulator and the current item, and its return value is ignored, so object accumulators need no return:

$stats = $orders->reduceInto(new OrderStats, function ($stats, $order) {

$stats->total += $order->amount;

$stats->count++;

$stats->largest = max($stats->largest, $order->amount);

});

For array or scalar accumulators, take the accumulator by reference:

$tagsMap = $posts->reduceInto([], function (&$map, $post) {

$post->tags->each(fn ($tag) => $map[$tag][] = $post->title);

});

See #60651.

counted() String Helper

Str::counted() and its Stringable equivalent pluralize a word and prepend the count in one call, a shorthand for plural($count, prependCount: true):

str('order')->counted(1); // "1 order"

str('order')->counted(2); // "2 orders"

See #60649.

Queue Improvements

Bulk SQS dispatches now go out through the SendMessageBatch API instead of one call per job, cutting the number of requests when pushing many jobs at once (#60645). The queue fake can now inspect reserved jobs, so tests can assert on jobs that have been picked up but not yet completed (#60644).

Other Fixes and Improvements

  • Pass deletedAtColumn through to assertSoftDeleted() and assertNotSoftDeleted() (#60657)
  • Allow mail config options to be defined without a name (#60668)
  • Terminate the default style value with a semicolon in ComponentAttributeBag::merge() (#60665)
  • Added tests for relative date where clauses and the date rule's past/future methods (#60675, #60687)

References