Reversible Form Prompts and a New Exceptions Facade in Laravel 11.4
Last updated on by Paul Redmond
This week, the Laravel team released v11.4, with reversible form Prompts, a new Exceptions facade, Enum support in the Collection::mapInto()
method, and more.
Introduce the Exceptions Facade
Nuno Maduro contributed the Exceptions
facade:
The Exceptions facade provides a consistent way to test exceptions in Laravel applications. Here is the list of methods that the Exceptions facade provides:
assertReported
assertReportedCount
assertNotReported
assertNothingReported
throwOnReport
throwFirstReported
Here's an example from the pull request description illustrating the Exceptions::fake()
method and assertReported()
method:
use Illuminate\Support\Facades\Exceptions; test('example', function () { Exceptions::fake(); $this->post('/generate-report', [ 'throw' => 'true', ])->assertStatus(503); // Service Unavailable Exceptions::assertReported(ServiceUnavailableException::class); // or Exceptions::assertReported(function (ServiceUnavailableException $exception) { return $exception->getMessage() === 'Service is currently unavailable'; });});
Read our Asserting Exceptions in Laravel Tests article for more details.
Livewire-style Directives
@devajmeireles contributed the ability to use Boolean-style directives, without any defined value:
{{-- Before --}} <x-fetch wire:poll /> {{-- Generates this HTML --}} <div ... wire:poll="wire:poll" /> {{-- After --}}<x-fetch wire:poll /> <div ... wire:poll />
Reversible Forms in Prompts
Luke Downing contributed form prompts, which are a grouped set of prompts for the user to complete. Forms include the ability to return to previous prompts and make changes without having to cancel the command and start over:
use function Laravel\Prompts\form; $responses = form() ->text('What is your name?', required: true) ->password('What is your password?', validate: ['password' => 'min:8']) ->confirm('Do you accept the terms?') ->submit();
Here's an example of using values from previous responses:
$responses = form() ->text('What is your name?', name: 'name') ->add(fn () => select('What is your favourite language?', ['PHP', 'JS']), name: 'language') ->add(fn ($responses) => note("Your name is {$responses['name']} and your language is {$responses['language']}")) ->submit();
See Pull Request #118 in the laravel/prompts
project for implementation details. This feature is already documented in the Prompts documentation.
mapInto
Collection Method
Add Support for Enums on Luke Downing contributed support for Enums on the Collection::mapInto()
method, which allows you to build up enums from an array of values:
public function store(Request $request){ $request->validate([ 'features' => ['array'], 'features.*' => [new Enum(Feature::class)], ]); $features = $request ->collect('features') ->mapInto(Feature::class); if ($features->contains(Feature::DarkMode)) { // ... }}
afterQuery()
Hook
An Günther Debrauwer contributed an afterQuery()
hook to run code after running a query:
$query->afterQuery(function ($models) { // Make changes to the queried models ...});
Here's a use-case example from the pull request's description:
// Before public function scopeWithIsFavoriteOf($query, ?User $user = null) : void{ if ($user === null) { return $query; } $query->addSelect([ // 'is_favorite' => some query ... ]);} $products = Product::withIsFavoriteOf(auth()->user())->get(); if (auth()->user() === null) { $products->each->setAttribute('is_favorite', false);}
And here's the code using the afterQuery()
hook:
// After public function scopeWithIsFavoriteOf($query, ?User $user = null) : void{ if ($user === null) { $query->afterQuery(fn ($products) => $products->each->setAttribute('is_favorite', false)); return; } $query->addSelect([ // 'is_favorite' => some query ... ]);} Product::withIsFavoriteOf(auth()->user())->get();
Release notes
You can see the complete list of new features and updates below and the diff between 11.3.0 and 11.4.0 on GitHub. The following release notes are directly from the changelog:
v11.4.0
- [11.x] Apc Cache - Remove long-time gone apc_* functions by @serpentblade in https://github.com/laravel/framework/pull/51010
- [11.x] Allowing Usage of Livewire Wire Boolean Style Directives by @devajmeireles in https://github.com/laravel/framework/pull/51007
- [11.x] Introduces
Exceptions
facade by @nunomaduro in https://github.com/laravel/framework/pull/50704 - [11.x]
afterQuery
hook by @gdebrauwer in https://github.com/laravel/framework/pull/50587 - Fix computed columns mapping to wrong tables by @maddhatter in https://github.com/laravel/framework/pull/51009
- [11.x] improvement test for string title by @saMahmoudzadeh in https://github.com/laravel/framework/pull/51015
- [11.x] Fix failing
afterQuery
method tests when using sql server by @gdebrauwer in https://github.com/laravel/framework/pull/51016 - [11.x] Fix: Apply database connection before checking if the repository exist by @sjspereira in https://github.com/laravel/framework/pull/51021
- [10.x] Fix error when using
orderByRaw()
in query before usingcursorPaginate()
by @axlon in https://github.com/laravel/framework/pull/51023 - [11.x] Add RequiredIfDeclined validation rule by @timmydhooghe in https://github.com/laravel/framework/pull/51030
- [11.x] Adds support for enums on
mapInto
collection method by @lukeraymonddowning in https://github.com/laravel/framework/pull/51027 - [11.x] Fix prompt fallback return value when using numeric keys by @jessarcher in https://github.com/laravel/framework/pull/50995
- [11.x] Adds support for
int
backed enums to implicitEnum
route binding by @monurakkaya in https://github.com/laravel/framework/pull/51029 - [11.x] Configuration to disable events on Cache Repository by @serpentblade in https://github.com/laravel/framework/pull/51032
- Revert "[11.x] Name of job set by displayName() must be honoured by S… by @RobertBoes in https://github.com/laravel/framework/pull/51034
- chore: fix some typos in comments by @laterlaugh in https://github.com/laravel/framework/pull/51037
- Name of job set by displayName() must be honoured by Schedule by @SCIF in https://github.com/laravel/framework/pull/51038
- Fix more typos by @szepeviktor in https://github.com/laravel/framework/pull/51039
- [11.x] Fix some doc blocks by @saMahmoudzadeh in https://github.com/laravel/framework/pull/51043
- [11.x] Add @throws ConnectionException tag on Http methods for IDE support by @masoudtajer in https://github.com/laravel/framework/pull/51066
- [11.x] Add Prompts
textarea
fallback for tests and add assertion tests by @lioneaglesolutions in https://github.com/laravel/framework/pull/51055 - Validate MAC per key by @timacdonald in https://github.com/laravel/framework/pull/51063
- [11.x] Add
throttle
method toLazyCollection
by @JosephSilber in https://github.com/laravel/framework/pull/51060 - [11.x] Pass decay seconds or minutes like hour and day by @jimmypuckett in https://github.com/laravel/framework/pull/51054
- [11.x] Consider after_commit config in SyncQueue by @hansnn in https://github.com/laravel/framework/pull/51071
- [10.x] Database layer fixes by @saadsidqui in https://github.com/laravel/framework/pull/49787
- [11.x] Fix context helper always requiring
$key
value by @nikspyratos in https://github.com/laravel/framework/pull/51080 - [11.x] Fix
expectsChoice
assertion with optionalmultiselect
prompts. by @jessarcher in https://github.com/laravel/framework/pull/51078