Laravel 7.0 is Here, Introducing Airlock (Sanctum)

Spring is almost here, but Laravel 7 couldn’t wait for it. Six months after Laravel 6, the next major release is out now and continues with its awesome new features and improvements. After version 6, Laravel is now following semver and will release a major version every six months. In this post, we will cover the essential features and improvements that come with Laravel 7.

Table of Contents:

A Quick Preview of Laravel 7.0

Laravel 7 keeps with the improvements and doesn’t seem to slow down in any way. The new major version includes Laravel Airlock, custom Eloquent casts, Blade component tags, better routing speed, a new HTTP client, fluent string operations, CORS support, Speed improvements in Route Caching, Artisan test command, and many more features.

Laravel Airlock (Sanctum)

Laravel Airlock (now known as Sanctum) offers a featherweight authentication system for single-page applications (SPAs), mobile apps, as well as simple, token-based APIs. Airlock offers all of your application users the capability to generate multiple API tokens for their accounts. Those tokens can be granted abilities that specify all actions that the tokens may perform.

API tokens

Laravel Airlock is here mainly to solve two problems. First and foremost, it’s a simple package that issues API tokens to your users. This particular feature is inspired by GitHub “access tokens.” For example, if the “account settings” of your app has a screen for users to generate API tokens for their accounts, Airlock can be used to generate and manage those tokens. Such tokens usually have an extensive expiration time, but the user can revoke them whenever they wish.

Airlock offers the feature via storing user API tokens in a database table, authenticating incoming requests through the Authorization header, which contains a valid API token.

SPA Authentication

If you are going to use Laravel Airlock, you are not obligated in any way to use it for both API token authentication and SPA Authentication. You can use it only for one of the features, and you will still be benefiting when it comes to convenience.

With that said, the second feature Airlock offers is a simple way to authenticate single-page applications (SPAs) that have to communicate with an API, powered by Laravel. These SPAs could exist in the same repository as your actual Laravel application, or they might be a completely separate repository, such as SPAs that are created using Vue CLI.

For the SPA Authentication feature, Airlock doesn’t use any tokens. Instead, it uses the built-in cookie-based session authentication services that Laravel has. That offers benefits such as CSRF protection, session authentication, in addition to protecting against authentication credentials leakages. Laravel Airlock will attempt to use cookies for authentication only if the incoming request comes from your own SPA frontend.

For more information on Laravel Airlock, consult the official Airlock documentation.

Custom Eloquent Casts

You probably know that Laravel has a variety of helpful cast types. However, you may still occasionally have to define your own cast types. Now, you can accomplish that goal by defining a class that puts the CastsAttributes interface to use.

Classes implementing this interface have to define a get and set method. The get method is to transform a raw value from the database into a cast value, and the set method has to transform a cast value into a raw value, which can be stored in the database.

Here is an example, where we are going to re-implement the built-in json cast type as a custom cast type:

<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class Json implements CastsAttributes
{
    /**
     * Cast the given value.
     *
     * @param \Illuminate\Database\Eloquent\Model $model
     * @param string $key
     * @param mixed $value
     * @param array $attributes
     * @return array
     */
    public function get($model, $key, $value, $attributes)
    {
        return json_decode($value, true);
    }
    /**
     * Prepare the given value for storage.
     *
     * @param \Illuminate\Database\Eloquent\Model $model
     * @param string $key
     * @param array $value
     * @param array $attributes
     * @return string
     */
    public function set($model, $key, $value, $attributes)
    {
        return json_encode($value);
    }
}

After you have a defined custom cast type, you can attach it to a model attribute by using its class name:

<?php
namespace App;
use App\Casts\Json;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'options' => Json::class,
    ];
}

In case you want to learn how to write custom Eloquent casts, you can check the official Eloquent documentation.

Blade Component Tags and Improvements

Blade components got an overhaul and now allow tag-based rendering, attribute management, component classes, inline new components, etc. As you can see, the Blade components overhaul is quite extensive, so if you want thorough information on the matter, you can go ahead and check the full Blade component documentation.

To sum it up, now a component can have an associated class that specifies the data it accepts. All of the public properties and methods that are defined on a component class would automatically be made available to the component view. You can use the included $attribute variable (which is a bag instance) to manage all extra HTML attributes that are specified on the component.

Here’s an example, where it’s assumed that an App\View\Components\Alert component has been defined in such manner:

<?php
namespace App\View\Components;
use Illuminate\View\Component;
class Alert extends Component
{
    /**
     * The alert type.
     *
     * @var string
     */
    public $type;
    /**
     * Create the component instance.
     *
     * @param string $type
     * @return void
     */
    public function __construct($type)
    {
        $this->type = $type;
    }
    /**  
    * Get the class for the given alert type.
     *
     * @return string
     */
    public function classForType()
    {
        return $this->type == 'danger' ? 'alert-danger' : 'alert-warning';
    }
    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\View\View|string
     */
    public function render()
    {
        return view('components.alert');
    }
}

And, assuming the component’s Blade template has been defined like:

<!-- /resources/views/components/alert.blade.php -->
<div class="alert {{ $classForType() }}" {{ $attributes }}>
    {{ $heading }}
    {{ $slot }}
</div>

You can render the component in another Blade view using the component’s tag:

<x-alert type="error" class="mb-4">
    <x-slot name="heading">
        Alert content...
    </x-slot>
 Default slot content...
 </x-alert>

This is only a tiny sample of the Blade component functionality after the overhaul in Laravel 7. This sample does not show anonymous components, inline view components, or a variety of other features. 

Note:
Laravel states that the previous @component syntax for Blade components hasn’t and won’t be removed.

HTTP Client

With the new update, Laravel now offers an expressive, minimal API around the Guzzle HTTP client. This API allows you to make quick ongoing HTTP requests in order to communicate with other web apps. Laravel’s Guzzle wrapper has a focus on its most common use cases, and on providing great developer experience. For example, the client makes it really easy to POST and interface with JSON data:

use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
    'X-First' => 'foo'
    'X-Second' => 'bar'
])->post('http://test.com/users', [
    'name' => 'Taylor',
]);
return $response['id'];

Additionally, the HTTP client offers amazing, ergonomic testing functionality:

Http::fake([
    // Stub a JSON response for GitHub endpoints...
    'github.com/*' => Http::response(['foo' => 'bar'], 200, ['Headers']),
    // Stub a string response for Google endpoints...
    'google.com/*' => Http::response('Hello World', 200, ['Headers']),
    // Stub a series of responses for Facebook endpoints...
    'facebook.com/*' => Http::sequence()
                            ->push('Hello World', 200)
                            ->push(['foo' => 'bar'], 200)
                            ->pushStatus(404),
]);

If you wish to learn more about the HTTP client and its features, go check out the HTTP client documentation.

Fluent String Operations

You probably are familiar with Laravel’s Illuminate\Support\Str class, which offers a number of string manipulation functions that can be quite helpful. Now, with, Laravel 7 you have at your disposal even more object-oriented, fluent string manipulation library, which is built on top of those functions. You have the option to create a fluent Illuminate\Support\Stringable object by using the Str::of method. You can then chain a variety of methods onto the object if you wish to manipulate the string:

return (string) Str::of(' Laravel Framework 6.x ')
                    ->trim()
                    ->replace('6.x', '7.x')
                    ->slug();

Again, if you want access to more information on all methods available via fluent string manipulation, consult the full documentation from Laravel itself.

Improvements in Route Model Binding

Key Customization

If you want to resolve Eloquent models via a column that differs from id, you can do that now. Laravel 7 allows developers the specification of columns in the route parameter definition.

Route::get('api/posts/{post:slug}', function (App\Post $post) {
    return $post;
});

Automatic Scoping

Sometimes you may have to bind multiple Eloquent models in a single route definition, and thus you may decide to scope the second Eloquent model to be a child of the first one. Consider the following situation, which gets a blog post by slug for a specified user:

use App\Post;
use App\User;
Route::get('api/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
    return $post;
});

When you use a custom keyed implicit binding as a nested route parameter, Laravel 7 would automatically scope the query and retrieve the nested model by its parent. The framework does that by using conventions to guess the relationship name on the parent. So, in the particular case, the assumption would be that the User model has a relationship named posts (the plural of the route parameter name), which can be used to retrieve the Post model.

For further information on route model binding, you can visit and check Laravel’s routing documentation.

Speed Improvements in Route Caching

Laravel 7 also includes a new method when it comes to matching compiled and cached routes, which were cached via the route:cache Artisan command. On larger applications (such with 800 or more routes), those improvements can result in doubling the speed for requests per second, when on a simple “Hello World” page. Additionally, no changes to your app are needed.

CORS Support

Laravel 7 comes with first-party support for configuring Cross-Origin Resource Sharing (CORS) OPTIONS request responses. That’s made possible by integrating the Laravel CORS package. The default Laravel application skeleton also includes a new CORS configuration.

If you need further information about the CORS support in Laravel 7.x, you can check their CORS documentation.

Artisan test Command

Now you can also use the test Artisan command for running your tests. The Artisan test runner offers a beautiful console UX and additional info in regards to the currently running test. Furthermore, the runner would automatically stop on the first test failure.

php artisan test

All arguments that could be passed to the phpunit command can also be passed to the Artisan test command:

php artisan test --group=feature

Final Thoughts

Laravel keeps getting better and better. We can only imagine what’s in store for us in the future. If you are currently using Laravel 6.x or older and want to upgrade to Laravel 7 and test all its awesome new features right away, we suggest that you create a manual backup first.

If you enjoyed this article, then you’ll love FastComet’s Laravel SSD Cloud hosting platform. Experience increased power, flexibility, and control for your applications.

Also, keep in mind that Laravel 7 requires PHP 7.3 or better. Of course, we suggest that you use the latest version, which is currently PHP 7.4. For the complete Laravel 7.0 upgrade instructions, you may follow the official Laravel Upgrade Guide. Happy coding, everyone!

Joseph

Joseph is part of the FastComet Marketing team. With years of content writing experience behind him, it's one of his favorite activities. Joseph takes part in the SEO of the FastComet website and blog. His goal is to write comprehensive posts and guides, always aiming to help our clients with essential information. Joseph also has a thirst for knowledge and improvement, which makes the hosting environment a perfect place for him.