Laravel 9 would be release this January of 2021, Here a top of my favorite additions to the framework during 2021.
A lot of this features are already available, thankfully the release process now is softer and we can enjoy a lot of this features with minor releases.
10 Allow "can" Middleware Chaining in the Route Definition
There is a new can method to use instead of a middleware string param:
// instead of this
Route::put('/post/{post}', function (Post $post) {
    // The current user may update the post...
})->middleware('can:update,post');
// Using the new can() method
Route::put('/post/{post}', function (Post $post) {
    // The current user may update the post...
})->can('update', 'post');
9 Conditional Validation Rules
It will validate (pass) a rule when a condition returns true:
request()->validate([
    'name' => 'required|string|min:6',
    'password' => [
        'required',
        'string',
        Rule::when(true, ['min:5', 'confirmed'])
    ],
]);
8 Ignore Trashed Models in Unique Validation Rule
It adds a convenient helper to ignore trashed records:
// Before
[
    'email'=> [
        Rule::unique('users')->whereNull('deleted_at'),
    ],
];
// After
[
    'email'=> [
        Rule::unique('users')->ignoreTrashed(),
    ],
];
7 Support "With Trashed" On Routes
Previously a trashed model was not able to be resolve with route model binding, now by adding this method it is posible:
Route::post('/user/{user}', function (ImplicitBindingModel $user) {
    return $user;
})->middleware(['web'])->withTrashed();
6 Password Validation Rule Object
Is a very common requirement to validate passwords with multiple rules like has at least one Uppercase, Lowercase, has a symbol, has a number, now it is very easy to implement with Password Rule Object:
<?php
$request->validate([
    'password' => [
        'required',
        'confirmed',
        Password::min(8)
            ->mixedCase()
            ->letters()
            ->numbers()
            ->symbols()
            ->uncompromised(),
    ],
]);
5 Disabling Lazy Loading
With this change the app would throw an exception if there is a model that is not returning eager loading relationships.
It requires to register this change in AppServiceProvider.php:
// app/Providers/AppServiceProvider.php
public function boot()
{
    Model::preventLazyLoading(! app()->isProduction());
}
Now you must use eager loading like this: $user->with('posts'); or $user->load('posts')
4 Logging With Context
// Middleware example
/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 */
public function handle($request, Closure $next)
{
    $requestId = (string) Str::uuid();
    Log::withContext([
        'request-id' => $requestId
    ]);
    return $next($request)->header('Request-Id', $requestId);
}
3 Prunable Models
Nuno Maduro adds an amazing feature to the framework, an ability to remove obsolete records by making Laravel models "prunable":
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable; // or MassPrunable
class Post extends Model
{
    use Prunable; // or MassPrunable
    /**
     * Determines the prunable query.
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function prunable()
    {
        return $this->where('created_at', '<=', now()->subMonth());
    }
}
You can choose between prunable or massPrunable the main difference between both is that prunable method would delete a model and fired eloquent model events and massPrunable only delete every model that match the condition quietly.
2 Enforce Implicit Route Model Scoping
There are cases where you have a nested routes relationship and it would be nice to validate that the second model is child from the first one, now it is available by using scopeBindings() method.
Route::get('/posts/{post}/comments/{comment}', function (Post $post, Comment $comment) {
    return $comment;
})->scopeBindings();
1 Mysql & Postgres FullTextSearch
You can search a term in different columns with this method:
// it search the word Laravel in title and body columns
$post = DB::table('posts')
    ->whereFullText(['title', 'body'], 'Laravel')
    ->get();
Bonus Merge Validated Input
Sometimes we need to "automatically" merge to a request fields some value by default or as a result of a service class, etc... now it is really easy to add:
$validator = Validator::make(
    ['name' => 'Taylor'],
    ['name' => 'required']
);
$validator->safe()->merge(['role' => 'Admin']);
User::create($validator->safe()->all());
// user would be stored as Taylor and with admin role
There are a lot of features that deserves a place here, but for the sake of keep this post short I am going to mention very briefly some of them that you can find useful
- Configurable "Remember me" cookie from config file - config/app.php
- New AssertIfModelExists Assertion (sugar syntax for - assertDatabaseHas())
- Make Model Artisan command new flags ( - --test,- --pest,- --requests, etc)
- New Dump TestResponse Methods ( - dd(),- dump(),- dumpHeaders(), etc)
- New Status Code Checks ( - $response->forbidden(),- $response->notFound(), etc ...)
- Validate Multiple Date Formats 
- Attribute Cast / Accessor Improvements 
- New Design for - routes:listcommand
Hopefully it adds more visibility to the new features that we have available in the framework Laravel.
Thanks for reading!
 

 
    
Top comments (0)