DEV Community

Ariel Mejia
Ariel Mejia

Posted on

Top 10 Additions to Laravel in 2021

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');
Enter fullscreen mode Exit fullscreen mode

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'])
    ],
]);
Enter fullscreen mode Exit fullscreen mode

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(),
    ],
];
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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(),
    ],
]);
Enter fullscreen mode Exit fullscreen mode

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());
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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());
    }
}
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:list command

Hopefully it adds more visibility to the new features that we have available in the framework Laravel.

Thanks for reading!

Discussion (0)