Laravel 9.12 Released
Published on by Paul Redmond
The Laravel team released 9.12 with delaying notifications per channel, sharing logging context across channels, preventing stray HTTP requests while testing, and more:
Laravel 9.12.0 has been released with a couple of cool new features 💅
— Taylor Otwell 🪐 (@taylorotwell) May 10, 2022
First - prevent any stray outgoing HTTP requests while testing using the new "preventStrayRequests" method contributed by @timacdonald87. 🚧 pic.twitter.com/TQUVgkkbiT
Closure-based Exception Testing
Karel Faille contributed a assertThrows()
method which adds a way to test exception handling using closures:
// Ensure that an exception is thrown$this->assertThrows(fn () => throw Exception('')); // Ensure that a specific type of exception is thrown$this->assertThrows( fn () => (new SomeActionThatThrowsExceptions)->execute(), CustomException::class); // Ensure that an exception is thrown with a specific message$this->assertThrows(fn () => throw Exception('My message'), Exception::class, 'My message');
Force HTTP Requests to Be Faked in Tests
Tim MacDonald contributed the ability to force all HTTP requests using Laravel's HTTP client to be faked. If an HTTP request is not faked in a test, the test will throw an exception:
protected function setUp(): void{ parent::setUp(); Http::preventStrayRequests();} public function testItDoesTheThingWithoutFaking(): void{ $this->post('endpoint-that-utilises-the-http-facade'); // RuntimeException: Attempted request to [https://acme.com] without a matching fake. /* ... */}
"Throw If" HTTP Client Method
@denniseilander contributed a throwIf()
method to the HTTP client that will throw an exception if the condition evaluates to true
:
// Throws RequestExceptionreturn Http::baseUrl('https://foo.bar') ->throwIf(true) ->get('not-found'); // Doesn't throwreturn Http::baseUrl('https://foo.bar') ->throwIf(false) ->get('not-found');
Allow Passing Key/Value Arrays to Artisan Options and Arguments
Jesper Noordsij contributed passing key/value arrays to getArguments
and getOptions
on Artisan commands for a slightly easier interface.
// Also, it is possible to skip those you don't want to use without providing/copying the default value // e.g.public function getArguments(){ return [ ['name' => 'argument', 'default' => 'default'] ]; // which previously would have been... // return [ // ['argument', null, '', 'default'] // ];}
See Pull Request #42268 for more details.
New More Condition Methods
Patrick O'Meara contributed the inverse of whereMorphedTo
and orWhereMorphedTo
methods. Here's an example from the PR tests:
$model = new EloquentBuilderTestModelParentStub; $this->mockConnectionForModel($model, ''); $relatedModel = new EloquentBuilderTestModelCloseRelatedStub; $relatedModel->id = 1; $builder = $model->whereNotMorphedTo('morph', $relatedModel); $this->assertSame('select * from "eloquent_builder_test_model_parent_stubs" where not ("morph_type" = ? and "morph_id" = ?)', $builder->toSql()); $this->assertEquals([$relatedModel->getMorphClass(), $relatedModel->getKey()], $builder->getBindings());
Check out Pull Request #42264 for more details.
Share Logging Context Across Channels and Stacks
Tim MacDonald contributed sharing contextual information across all logging channels:
// In a service provider...public function boot(){ Log::shareContext([ 'invocation-id' => (string) Str::uuid(), ]);}
See contextual information in the logging documentation.
Delaying Notifications Per Channel
You can pass an array to the delay method to specify the delay amount for specific channels:
$user->notify((new InvoicePaid($invoice))->delay([ 'mail' => now()->addMinutes(5), 'sms' => now()->addMinutes(10),]));
You can also define a withDelay
method on the notification class:
/** * Determine the notification's delivery delay. * * @param mixed $notifiable * @return array */public function withDelay($notifiable){ return [ 'mail' => now()->addMinutes(5), 'sms' => now()->addMinutes(10), ];}
See Delaying Notifications Per Channel in the notifications documentation.
Release Notes
You can see the complete list of new features and updates below and the diff between 9.11.0 and 9.12.0 on GitHub. The following release notes are directly from the changelog:
v9.12.0
Added
- Added closure based exceptions testing (#42155)
- Allow forcing requests made via the Http client to be faked (#42230)
- Added 'throwIf' method to PendingRequest (#42260)
- Allow passing key/value arrays to getArguments and getOptions (#42268)
- Add whereNotMorphedTo, orWhereNotMorphedTo (#42264)
- Add method to extend localeArray generation (#42275)
- Added ability to set delay per channel based on notifiable instance (#42239)
- Added Illuminate/Pagination/CursorPaginator::onLastPage() (#42301)
- Added findOr method to Query/Builder (#42290)
Fixed
- Fix too many channels with pusher broadcasting (#42287)
- Fix Str::Mask() for repeating chars (#42295)
- Fix EventFake::assertListening() for asserting string-based observer listeners (#42289)
- Fixed Loose comparison causes the value not to be saved (#41337)
- Fix multiple dots for digits_between rule (#42330)
Changed
- Enable to modify HTTP Client request headers when using beforeSending() callback (#42244)
- Make throttle lock acquisition retry configurable for concurrency limiter (#42242)
- Defers expanding callables on Factories (#42241)
- Add wherehas soft deleting scopes (#42100)
- Improve password checks (#42248)
- Set relation parent key when using forceCreate on HasOne and HasMany relations (#42281)
- Make sure the prefix override behaviours are the same between phpredis and predis drivers (#42279)
- Share logging context across channels and stacks (#42276)