What’s New in Laravel 8?

#2 A Model Directory!

Natalie Mclaren
Better Programming

--

Photo by Henri L. on Unsplash

Has it been six months already?! It sure has. You know what that means: A new Laravel version is here — Laravel 8!

Laravel 8 was released two days ago with a bunch of useful updates I was excited to hear about. In this article, I’ll go over what’s changed. For full details visit the release note here.

Disclaimer: Laravel will continue to provide bug fixes for this version for the next six months and security fixes for the next year.

1. Laravel Jetstream

Version 8 introduces Laravel Jetstream — an application scaffolding for the framework with a stylish user dashboard. Jetstream handles everything from login, registration, and email verification, to session management and optional team management. It is designed with a highly customisable CSS framework, Tailwind, and offers you a choice between Livewire and Inertia.

To get started, run the following:

composer global require laravel/installerlaravel new laravel-8 --jet
npm install && npm run devphp artisan serve

Make sure to add your database name to the .env file and migrate it.

Upon refreshing you’ll see the usual Laravel welcome page (albeit looking somewhat different and much slicker.) Click the register link to register your account and navigate to /dashboard to view your new dashboard:

At this point, if you run php artisan vendor:publish — tag=jetstream-views and look under resources/views/vendor/jetstream/components you’ll see a list of available components to use right out of the box. welcome.blade.php for example, would be used in your application as <x-jet-welcome /> .

2. A Models Directory

Lo and behold, the moment we’ve all been waiting for — a models directory!

Prior to version 8, all existing and newly generated models sat within the root of the framework’s /app directory. Most would then create a Models sub-folder, move all models to said folder and change their namespaces to reflect the new path. I think I speak for the community when I say we weren’t keen on this setup! Otwell has more than made up for this, however, with this latest update. All model generator commands have been updated to place new models inside a Models folder. If the directory doesn’t already exist, one will be created for you, along with your new model. Happy days!

3. Model Factory Classes

Class-based factories have replaced the model factories we knew before.

Laravel 7

/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
factory(App\User::class, 50)->create()->each(function ($user) {
$user->posts()->save(factory(App\Post::class)->make());
});
}

Laravel 8

use App\Models\User;/**
* Run the database seeders.
*
* @return void
*/
public function run()
{
User::factory()
->times(50)
->hasPosts(1)
->create();
}

4. Migration Squashing

This cool new feature makes bulky migration folders a thing of the past. Migration squashing has been introduced, enabling all migrations to be squashed into a single SQL file.

Running the following will create a schema folder under database with an SQL file containing CREATE TABLE queries for all of your migrations:

php artisan schema:dump

To remove the migrations leaving only the SQL file, run the following:

php artisan schema:dump --prune

php artisan migrate will then run the SQL schema first, followed by any new migrations not yet part of the file under migrations. To include new migrations to the schema file, simply run the schema:dump command again.

5. Job Batching

Laravel’s new job batching feature allows multiple jobs to be dispatched using the new batch method of the Bus facade. You may of course then use methods like then , finally and catch to customise their completion. The basic implementation is below:

6. Improved Rate Limiting

Setting a hit rate limit on routes can now be done in a more flexible and encapsulated way than in the previous version. Using the RateLimiter facade’s for method, limit times can be set and may even be dynamic based on the received $request.

Laravel 7

Route::middleware('auth:api', 'throttle:60,1')->group(function () {
Route::get('/user', function () {
//
});
});

Laravel 8

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;
RateLimiter::for('global', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100);
});

To make use of these limits on certain routes, apply them as you would any middleware using the same name you passed into the for method:

Route::middleware(['throttle:global'])->group(function () {
Route::post('/audio', function () {
//
});
Route::post('/video', function () {
//
});
});

Backwards compatibility has been maintained, however, to make use of the previous release’s throttle middleware API.

7. Improved Maintenance Mode

Despite having your application on maintenance mode, Laravel allows for specific users to view it, as long as they meet a certain condition. This condition has now changed — previously an IP address was required, now it is a secret token.

Laravel 7

php artisan down --allow=127.0.0.1 --allow=192.168.0.0/16

Laravel 8

php artisan down --secret="1630542a-246b-4b66-afa1-dd72a4c43515"

After setting the token, Laravel will know to look for it when a user hits the URL. So the following will display the application:

https://test-site.com/1630542a-246b-4b66-afa1-dd72a4c43515

Once the cookie has been saved to your browser, you will be able to revisit the application just as you would outside of maintenance mode!

Pre-rendering a maintenance mode view

As part of the improvements to maintenance mode, you may now pre-render a specific maintenance view.

Why is this so important?

Well, before this, if you ran php artisan down during deployment, there was still a chance users could encounter an error if they hit the application before any dependencies had updated to reflect the new mode. With this addition, a maintenance mode view of your choice can be specified and will be displayed immediately at the start of the request cycle, so there’s no waiting for the framework to boot.

php artisan down --render="errors::503"

8. Closure Dispatch/Chain

A new catch method has been added which will be executed if a queued closure fails to complete successfully. This is very useful for customising what happens in case of that failure.

Laravel 7

$podcast = App\Podcast::find(1);dispatch(function () use ($podcast) {
$podcast->publish();
});

Laravel 8

$podcast = App\Podcast::find(1);dispatch(function () use ($podcast) {
$podcast->publish();
})->catch(function (Throwable $e) {
// This job has failed...
});

9. Dynamic Blade Components

You now no longer need to hardcode component names onto a page, they can instead be rendered based on a runtime value or variable!

Laravel 7

php artisan make:component Info

To display the component you would then use the following command:

<x-info />

Laravel 8

<x-dynamic-component :component="$componentName" />

Let’s see how we might implement this.

First, create a component using php artisan make:component <component-name> . I’ve decided to call mine success:

Then pick a route and pass down the relevant data to the view via its controller:

I chose to render my dynamic component inshow.blade.php. Navigating to /user/profile from your dashboard should now display your success text:

This is extremely useful for dynamically loading success or error components. Simply pass down the name to the view (in this example the variable was message and value was success), and as long as there’s a component with that name, Laravel will dynamically render it for you.

10. Event Listener Improvements

Event listeners have been improved to include the registration of Closure based event listeners. This can be done by only passing the Closure to the Event::listen method. Additionally, these new Closure based event listeners can also be marked as queueable and, like queued jobs, the usual existing methods — onConnection , onQueue and delay — may be used to customise the execution of the queued listener.

Event::listen(queueable(function (PodcastProcessed $event) {
//
}));

Marking as queueable is, of course, optional and can be removed.

11. Time Testing Helpers

This new update brings us helpers that allow the modification of timestamps returned when testing. The introduction of travel() can be used in conjunction with the famous now() to go into the future, travel back in time, and return back to the present.

// Travel into the past
$this->travel(-5)->hours();
// Come back to the present
$this->travelBack();

12. Automatic Reloading on Environment Changes

Any changes detected in the .env file will now trigger an automatic reload, removing the need for a manual stop and restart of the serve command.

13. Tailwind Becomes Default Styling for the Paginator

But Bootstrap 3 and 4 views will still remain available!

14. Routing Namespace Updates

The RouteServiceProvider class in versions 7 and below contained a $namespace property. This property’s value was then prefixed to all routes set out in the routes files. This newer version of Laravel removes the namespace and instead class names are used directly in routes files.

Laravel 7

class RouteServiceProvider extends ServiceProvider{/*** This namespace is applied to your controller routes.* In addition, it is set as the URL generator's root namespace.** @var string*/protected $namespace = 'App\Http\Controllers';}

Thus, doing the below would work and the framework would know exactly where your controller sat:

Route::get('/users', 'UserController@index');

Laravel 8

Introducing a new way to set out routes:

use App\Http\Controllers\UserController;Route::get('/users', [UserController::class, 'index']);

That’s all of the new and updated features announced in the Laravel 8 release. I hope you enjoyed reading about them!

Do you have any favourites? Let me know in the comments below. Happy coding!

Never want to miss an update or new release again? Check out my free web app where you can see all the latest Github releases for today’s most used languages and frameworks!

--

--