Laravel 10.14 Released
Published on by Paul Redmond
This week, the Laravel team released v10.14 with a new can
validation rule, define custom Gate denial response, global HTTP client middleware, HTTP client convenience methods, and more:
Recently merged into Laravel, the Rule::can validation rule, allowing you to authorize an ability on form inputs! 🤩 This allows you to move some authorization logic from the controller and into the form request -- and display a validation error, rather than handling it yourself. pic.twitter.com/UvC52Q8WZa
— Steve Bauman (@ste_bau) June 22, 2023
can
validation rule
The Steve Bauman contributed the Rule::can()
validation rule, which provides a way to authorize an ability for a given form field. Here's the example given in Pull Request #47371. Given the following PostPolicy
:
// Given the following policyclass PostPolicy{ // ... public function updateAuthor(User $user, Post $post) { return $user->isAdmin(); }}
We can validate that the user has the ability to update the author:
use App\Models\Post; class PostRequest extends FormRequest{ public function rules() { return [ 'author' => Rule::can('update-author', Post::class, $this->route('post')), 'title' => '...', 'body' => '...', ]; }}
Gate@inspect()
Set a custom response for denial within Luke Kuzmish contributed the ability to set a response returned when a Gate's inspect()
method fails. For example, when using in conjunction with the can()
middleware:
class AppServiceProvider extends ServiceProvider{ public function boot() { Gate::setDenialResponse(Response::denyAsNotFound()); }}
Global HTTP middleware
Tim MacDonald contributed the ability to define global HTTP client middleware that is applied to every request made with the HTTP client:
// In a service provider... use Illuminate\Support\Facades\Http; // Global request middlewareHttp::globalRequestMiddleware( fn ($request) => $request->withHeader('User-Agent', 'Laravel Framework/1.0')); // Global response middlewareHttp::globalResponseMiddleware( fn ($response) => $response->withHeader('X-Finished-At', now()->toDateTimeString())); // Complete global middleware that wraps both request and responseHttp::globalMiddleware(function ($handler) { return function ($request, $options) use ($handler) { $startedAt = now(); return $handler($request, $options) ->then(fn ($response) => $response->withHeader( 'X-Duration', $startedAt->diffInMilliseconds(now()) )); };});
You can also define one-time middlware—check out all the details in Pull Request #47525 to see what's possible!
withHeader()
method to PendingRequest
Add a Ralph J. Smit contributed a withHeader
method to set a singular header when using the HTTP client:
// Using an arrayHttp::baseUrl(config('services.active-campaign.endpoint') . '/api/3') ->withHeaders([ 'Api-Token' => config('services.active-campaign.token') ]) ->acceptJson(); // Setting a single header using `withHeader()`Http::baseUrl(config('services.active-campaign.endpoint') . '/api/3') ->withHeader('Api-Token', config('services.active-campaign.token')) ->acceptJson();
withQueryParameters
convenience method to the HTTP client
Add Matthieu Napoli contributed a withQueryParameters()
method as a convenience for defining query parameters that should always be defined on an HTTP request:
// Using `withOptions()`Http::baseUrl('https://api.convertkit.com/v3/') ->withOptions([ 'query' => [ 'api_secret' => config('services.convertkit.api_secret'), ], ]) ->acceptJson(); // Using the new `withQueryParameters()` methodHttp::baseUrl('https://api.convertkit.com/v3/') ->withQueryParameters([ 'api_secret' => config('services.convertkit.api_secret'), ]) ->acceptJson();
Release Notes
You can see the complete list of new features and updates below and the diff between 10.13.0 and 10.14.0 on GitHub. The following release notes are directly from the changelog:
v10.14.0
- [10.x] Add test for
withCookies
method in RedirectResponse by @milwad-dev in https://github.com/laravel/framework/pull/47383 - [10.x] Add new error message "SSL: Handshake timed out" handling to PDO Dete… by @yehorherasymchuk in https://github.com/laravel/framework/pull/47392
- [10.x] Add new error messages for detecting lost connections by @mfn in https://github.com/laravel/framework/pull/47398
- [10.x] Update phpdoc
except
method in Middleware by @milwad-dev in https://github.com/laravel/framework/pull/47408 - [10.x] Fix inconsistent type hint for
$passwordTimeoutSeconds
by @devfrey in https://github.com/laravel/framework/pull/47414 - Change visibility of
path
method in FileStore.php by @foremtehan in https://github.com/laravel/framework/pull/47413 - [10.x] Fix return type of
buildException
method by @milwad-dev in https://github.com/laravel/framework/pull/47422 - [10.x] Allow serialization of NotificationSent by @cosmastech in https://github.com/laravel/framework/pull/47375
- [10.x] Incorrect comment in
PredisConnector
andPhpRedisConnector
by @hungthai1401 in https://github.com/laravel/framework/pull/47438 - [10.x] Can set custom Response for denial within
Gate@inspect()
by @cosmastech in https://github.com/laravel/framework/pull/47436 - [10.x] Remove unnecessary param in
addSingletonUpdate
by @milwad-dev in https://github.com/laravel/framework/pull/47446 - [10.x] Fix return type of
prefixedResource
&prefixedResource
by @milwad-dev in https://github.com/laravel/framework/pull/47445 - [10.x] Add Factory::getNamespace() by @tylernathanreed in https://github.com/laravel/framework/pull/47463
- [10.x] Add
whenAggregated
method toConditionallyLoadsAttributes
trait by @akr4m in https://github.com/laravel/framework/pull/47417 - [10.x] Add PendingRequest
withHeader()
method by @ralphjsmit in https://github.com/laravel/framework/pull/47474 - [10.x] Fix $exceptTables to allow an array of table names by @cwilby in https://github.com/laravel/framework/pull/47477
- [10.x] Fix
eachById
onHasManyThrough
relation by @cristiancalara in https://github.com/laravel/framework/pull/47479 - [10.x] Allow object caching to be disabled for custom class casters by @CalebDW in https://github.com/laravel/framework/pull/47423
- [10.x] "Can" validation rule by @stevebauman in https://github.com/laravel/framework/pull/47371
- [10.x] refactor(Parser.php): Removing the extra "else" statement by @saMahmoudzadeh in https://github.com/laravel/framework/pull/47483
- [10.x] Add
UncompromisedVerifier::class
toprovides()
inValidationServiceProvider
by @xurshudyan in https://github.com/laravel/framework/pull/47500 - [10.x] Reindex appends attributes by @hungthai1401 in https://github.com/laravel/framework/pull/47519
- [10.x] Fix
ListenerMakeCommand
deprecations by @dammy001 in https://github.com/laravel/framework/pull/47517 - [10.x] Add
HandlesPotentiallyTranslatedString
trait by @xurshudyan in https://github.com/laravel/framework/pull/47488 - [10.x] update [JsonResponse]: using match expression instead of if-elseif-else by @saMahmoudzadeh in https://github.com/laravel/framework/pull/47524
- [10.x] Add
withQueryParameters
to the HTTP client by @mnapoli in https://github.com/laravel/framework/pull/47297 - [10.x] Allow
%
symbol in component attribute names by @JayBizzle in https://github.com/laravel/framework/pull/47533 - [10.x] Fix Http client pool return type by @srdante in https://github.com/laravel/framework/pull/47530
- [10.x] Use
match
expression inresolveSynchronousFake
by @osbre in https://github.com/laravel/framework/pull/47540 - [10.x] Use
match
expression incompileHaving
by @osbre in https://github.com/laravel/framework/pull/47548 - [10.x] Use
match
expression ingetArrayableItems
by @osbre in https://github.com/laravel/framework/pull/47549 - [10.x] Fix return type in
SessionGuard
by @PerryvanderMeer in https://github.com/laravel/framework/pull/47553 - [10.x] Fix return type in
DatabaseQueue
by @PerryvanderMeer in https://github.com/laravel/framework/pull/47552 - [10.x] Fix return type in
DumpCommand
by @PerryvanderMeer in https://github.com/laravel/framework/pull/47556 - [10.x] Fix return type in
MigrateMakeCommand
by @PerryvanderMeer in https://github.com/laravel/framework/pull/47557 - [10.x] Add missing return to
Factory
by @PerryvanderMeer in https://github.com/laravel/framework/pull/47559 - [10.x] Update doc in Eloquent model by @alirezasalehizadeh in https://github.com/laravel/framework/pull/47562
- [10.x] Fix return types by @PerryvanderMeer in https://github.com/laravel/framework/pull/47561
- [10.x] Fix PHPDoc throw type by @fernandokbs in https://github.com/laravel/framework/pull/47566
- [10.x] Add hasAny function to ComponentAttributeBag, Allow multiple keys in has function by @indykoning in https://github.com/laravel/framework/pull/47569
- [10.x] Ensure captured time is in configured timezone by @timacdonald in https://github.com/laravel/framework/pull/47567
- [10.x] Add Method to Report only logged exceptions by @joelharkes in https://github.com/laravel/framework/pull/47554
- [10.x] Add global middleware to
Http
client by @timacdonald in https://github.com/laravel/framework/pull/47525