Ramblings of a Tampa engineer
laravel/art - repo

Laravel has become the framework of choice for my hobby and work life. For that reason I enjoy following what is on the horizon. Every major version increase of Laravel always brings some interesting features. So this is the upcoming major features that caught my eye.


Maintenance Mode Overhaul - PR

This feature was a rarely needed, but highly appreciated when needed. If you've ever leveraged php artisan down to take your Laravel website offline temporarily. That page can still not work if you run into an issue with dependency installs or some low level package issue. This is because the entire Laravel framework needed to be booted in order to render the error page.

So lets talk through the new features from just an example run.

➜ php artisan down --redirect=/ --status=418 --secret=sekrit --render="errors::503"

What this does is:

  • Put the application offline
  • Redirect all routes to "/"
  • Use a custom HTTP Status (418 Teapot)
  • Set a secret to bypass maintenance mode (sets a cookie to allow site use)
  • Render a view file for the downtime.

Laravel does this by writing all the above parameters into a JSON file. The framework before booting checks if that file exists. If so, all the logic is contained to a different path of execution. So without Laravel booting it can render and do the logic required for the maintenance mode.

The view says 503, but the status code is 418 :)
➜  ~ curl -I http://127.0.0.1:8000
HTTP/1.0 418 I'm a teapot
Host: 127.0.0.1:8000

Queued Closures - PR

Sometimes you are writing code that is just too slow to run on the main thread. In those situations a Job is written. That Job can be queued asynchronously in Laravel, but the boilerplate to get that running for some types of jobs may be a lot.

Laravel will soon support its first namespace`d function of queueable which as the name suggests allows a closure of an Event to be directly attached to a listener.

use function Illuminate\Events\queueuable;

App\User::created(queueable(function ($user) {
    info($user->name);
}));

Better Model Support - PR

How many people throw models just into app/? For small projects sure - I do. For medium projects I love the organization of app/Models. For huge projects each component will have app/Models in its own directory state.

Laravel will now properly detect if you have an app/Models folder and use that instead for generation commands. Hopefully this drives package authors to no longer hard-code model locations.


Job Batching - PR

If you have a bunch of jobs and need to fire them all out and wait on the responses, then the batching enhancements is for you.

Bus::batch([
    new TestJob(),
    new TestBlogJob()
])->then(function (Batch $batch) {
    if ($batch->hasFailures()) {
        // die
    }
})->allowFailures()->dispatch();

Rate Limiting Enhancements - PR

For those who commonly rate limit applications - you might see a line like - 'throttle:6000,1' - what does that even mean? 6000 per 1 what?

Laravel has recognized this and introduce a new method for this. First off you have to generate a name for your rate limit - perhaps for downloads, uploads or even an expensive API.

RateLimiter::for('downloads', function (Request $request) {
    if ($request->user()->isPremium()) {
        return Limit::none();
    }

    Limit::perMinute(1)->by($request->ip());
});
A rate limiter for 1 download per minute, unlimited for premium members.

So at this point we have a named rate limit of downloads. So this can be used as a common middleware.

Route::middleware(['throttle:downloads'])->group(function () {
    // routes
});
Leveraging custom rate limit above.

So future contributors or coworkers can easily understand the purpose behind these rate limits.


Schema Dump - PR

As a project continues for years - I assume the migrations folder is quite heavy with files. This means every time the CI process or even a new contributors begins they have to sit through maybe minutes of migrations.

Migrations may even add and then remove columns or tables that aren't even in the finalized database structure.

The Rails project solved this by introducing a schema.rb file which is updated as migrations are ran which updates the flat file. The benefit as Rails describes it is as...

There is no need (and it is error prone) to deploy a new instance of an app by replaying the entire migration history. It is much simpler and faster to just load into the database a description of the current schema.
Guides - Ruby on Rails

So lets how Laravel did this. I'll start with a new Laravel 8 project and immediatly migrate and dump the schema.

➜  php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (864.55ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (244.85ms)
➜  php artisan schema:dump
Database schema dumped successfully.

So now I should try and refresh the database.

➜  php artisan migrate:fresh
Dropped all tables successfully.
Migration table created successfully.
Loading stored database schema: /home/ibotpeaches/Desktop/laravel/database/schema/mysql-schema.sql
Loaded stored database schema. (1,187.28ms)
Nothing to migrate.

So we can see Laravel leveraged the schema file and then didn't need to run any other migrations. Since this was a brand new project - the amount of migrations to process was just the ones Laravel gives you.

This will be interesting for large projects to try out for a real test and should greatly cut down the CI process for those large legacy projects you might have. (Granted legacy projects probably won't be upgrading to Laravel 8)


Conclusion

Laracon is online only this year on August 26. My gut (like every other Laracon) means we will probably have Laravel 8 launching and some other unannounced package/feature/service.

Tickets are only $29/person if you want to sign up. With that - I'm excited for this upcoming version for a couple of these features.