Laravel 8 is now released and includes many new features including Laravel Jetstream, a models directory, model factory classes, migration squashing, rate-limiting improvements, maintenance mode improved, time testing helpers, update routing namespace, and many more features.

The Laravel framework its components from your application or package, if you use a lower version such as 6.x or 7.x, since major releases of Laravel do include breaking changes. However, a new major version is released.

Laravel Jetstream

Laravel Jetstream improves upon the existing Laravel UI scaffolding found in previous versions. It provides a starting point for new projects, including login, registration, email verification, two-factor authentication, session management, API support via Laravel, and team management.

Models Directory

Laravel 8’s application skeleton includes an app/Models directory. All generator commands assume models exist in app/Models; however if this directory doesn’t exist, the framework will assume the application keeps models within the app/ folder

Model Factory Classes

Eloquent model factories are now class-based starting in Laravel 8, with improved support for relationships between factories (i.e., a user has many posts). I think you’ll agree how awesome the new syntax is for generating records via the new and improved model factories:

use App\Models\User;

User::factory()->count(21)->create();

// using a model state "suspended" defined within the factory class
User::factory()->count(7)->suspended()->create();

Migration Squashing

As you build your application, you may accumulate more and more migrations over time. This can lead to your migration directory becoming bloated with potentially hundreds of migrations. If you’re using MySQL or PostgreSQL, you may now “squash” your migrations into a single SQL file. To get started, execute the schema:dump command:

Attributes on Extended Blade Components

In Laravel 7 the child components didn’t have access to the $attributes passed to it. In Laravel 8 these components were enhanced and it is now possible to merge nested component attributes. This makes it easier to create extended components.

Job Batching

Laravel’s job batching feature allows you to easily execute a batch of jobs and then perform some action when the batch of jobs has completed executing.

The new batch method of the Bus facade may be used to dispatch a batch of jobs. Of course, batching is primarily useful when combined with completion callbacks. So, you may use the then, catch, and finally methods to define completion callbacks for the batch. Each of these callbacks will receive an Illuminate\Bus\Batch instance when they are invoked:

use App\Jobs\ProcessPodcast;
use App\Podcast;
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;
use Throwable;

$batch = Bus::batch([
    new ProcessPodcast(Podcast::find(1)),
    new ProcessPodcast(Podcast::find(2)),
    new ProcessPodcast(Podcast::find(3)),
    new ProcessPodcast(Podcast::find(4)),
    new ProcessPodcast(Podcast::find(5)),
])->then(function (Batch $batch) {
    // All jobs completed successfully...
})->catch(function (Batch $batch, Throwable $e) {
    // First batch job failure detected...
})->finally(function (Batch $batch) {
    // The batch has finished executing...
})->dispatch();

return $batch->id;

Improved Rate Limiting

Laravel’s request rate limiter feature has been augmented with more flexibility and power, while still maintaining backwards compatibility with previous release’s throttle middleware API. Rate limiters are defined using the RateLimiter facade’s for method.

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

RateLimiter::for('global', function (Request $request) {
    return Limit::perMinute(1000);
});

Rate limiters are defined using the RateLimiter facade’s for method. The for method accepts a rate limiter name and a closure that returns the limit configuration that should apply to routes that are assigned this rate limiter:

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

RateLimiter::for('global', function (Request $request) {
    return Limit::perMinute(1000);
});

Closure Dispatch / Chain catch

Using the new catch method, you may now provide a closure that should be executed if a queued closure fails to complete successfully after exhausting all of your queue’s configured retry attempts:

In Laravel 7 the child components didn’t have access to the $attributes passed to it. In Laravel 8 these components were enhanced and it is now possible to merge nested component attributes. This makes it easier to create extended components.

Sometimes you may need to render a component but not know which component should be rendered until runtime. In this situation, you may now use Laravel’s built-in dynamic-component component to render the component based on a runtime value or variable:

To learn more about Blade components, please consult the Blade documentation.

use Throwable;

dispatch(function () use ($podcast) {
    $podcast->publish();
})->catch(function (Throwable $e) {
    // This job has failed...
});

Event Listener Enhancements

Closure based event listeners may now be registered by only passing the closure to the Event::listen method. Laravel will inspect the closure to determine which type of event the listener handles. Like queued jobs, you may use the onConnectiononQueue, and delay methods to customize the execution of the queued listener:

Event::listen(queueable(function (PodcastProcessed $event) {
    //
})->onConnection('redis')->onQueue('podcasts')->delay(now()->addSeconds(10)));

Time Testing Helpers

Laravel users have enjoyed full control over time modification via the excellent Carbon PHP library. Laravel 8 brings this one step further by providing convenient test helpers for manipulating the time within tests:

public function testTimeCanBeManipulated()
{
    // Travel into the future...
    $this->travel(5)->milliseconds();
    $this->travel(5)->seconds();
    $this->travel(5)->minutes();
    $this->travel(5)->hours();
    $this->travel(5)->days();
    $this->travel(5)->weeks();
    $this->travel(5)->years();

    // Travel into the past...
    $this->travel(-5)->hours();

    // Travel to an explicit time...
    $this->travelTo(now()->subHours(6));

    // Return back to the present time...
    $this->travelBack();
}

Artisan serve Improvements

The Artisan serve command has been improved with automatic reloading when environment variable changes are detected within your local .env file. Previously, the command had to be manually stopped and restarted.

Controllers Routing Namespacing

No more double prefix issues! In previous versions of Laravel, the RouteServiceProvider had an attribute called namespace that was used to prefix the controllers in the routes files. That created a problem when you were trying to use a callable syntax on your controllers, causing Laravel to mistakenly double prefix it for you. This attribute was removed and now you can import and use it without the issue.

It can also be used for single action controllers that have the __invoke method.

use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);

Follow me!