Never Miss a Laravel Release 🚀
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
The can validation rule
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' => '...', ]; }}
Set a custom response for denial within Gate@inspect()
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!
Add a withHeader() method to PendingRequest
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();
Add withQueryParameters convenience method to the HTTP client
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
withCookiesmethod 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
exceptmethod in Middleware by @milwad-dev in https://github.com/laravel/framework/pull/47408 - [10.x] Fix inconsistent type hint for
$passwordTimeoutSecondsby @devfrey in https://github.com/laravel/framework/pull/47414 - Change visibility of
pathmethod in FileStore.php by @foremtehan in https://github.com/laravel/framework/pull/47413 - [10.x] Fix return type of
buildExceptionmethod 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
PredisConnectorandPhpRedisConnectorby @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
addSingletonUpdateby @milwad-dev in https://github.com/laravel/framework/pull/47446 - [10.x] Fix return type of
prefixedResource&prefixedResourceby @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
whenAggregatedmethod toConditionallyLoadsAttributestrait 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
eachByIdonHasManyThroughrelation 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::classtoprovides()inValidationServiceProviderby @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
ListenerMakeCommanddeprecations by @dammy001 in https://github.com/laravel/framework/pull/47517 - [10.x] Add
HandlesPotentiallyTranslatedStringtrait 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
withQueryParametersto 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
matchexpression inresolveSynchronousFakeby @osbre in https://github.com/laravel/framework/pull/47540 - [10.x] Use
matchexpression incompileHavingby @osbre in https://github.com/laravel/framework/pull/47548 - [10.x] Use
matchexpression ingetArrayableItemsby @osbre in https://github.com/laravel/framework/pull/47549 - [10.x] Fix return type in
SessionGuardby @PerryvanderMeer in https://github.com/laravel/framework/pull/47553 - [10.x] Fix return type in
DatabaseQueueby @PerryvanderMeer in https://github.com/laravel/framework/pull/47552 - [10.x] Fix return type in
DumpCommandby @PerryvanderMeer in https://github.com/laravel/framework/pull/47556 - [10.x] Fix return type in
MigrateMakeCommandby @PerryvanderMeer in https://github.com/laravel/framework/pull/47557 - [10.x] Add missing return to
Factoryby @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
Httpclient by @timacdonald in https://github.com/laravel/framework/pull/47525