TL;DR: Laravel 5.7 is a major release to, at time of writing, the most popular PHP framework on GitHub. Furthermore, Laravel Nova was also released. In this article, I'll cover the new features in Laravel 5.7 and several other changes and deprecations.

What's new in Laravel 5.7?

1. Symfony Dump Server Integration

Marcel Pociot, authored a package called laravel-dump-server. This package provides you a dump server, that collects all your dump call outputs. It's inspired by Symfony's Var-Dump Server.

Laravel 5.7 now officially ships with the laravel_dump-server package and makes it available via the Artisan command:

php artisan dump-server

All dump calls will be displayed in the console window once the server has started.

Laravel - Symfony Dump Server Integration Source: murze.be

2. Better Support For Filesystem

Laravel 5.7 ships with two new methods for reading and writing streams in the filesystem. They are readStream and writeStream methods for reading and writing streams respectively as shown in the example below:

Storage::disk('s3')->writeStream(
    'new-package.zip',
    Storage::disk('local')->readStream('local-package.zip')
);

3. Improved Artisan Command Testing

Laravel 5.7 provides a better approach for testing artisan commands.

Check out the example below:

This is an Artisan command:

Artisan::command('hackathon-starter:init', function () {
    $project = $this->ask('What type of project do you want to build?');

    $this->line('Initializing...');

    $answer = $this->choice('Which language do you program in?', [
        'pwa-on-steroids',
        'pwa-normal',
        'pwa-on-fire',
    ]);

    $this->line('Installing...');
});

You may now test the command above with the slick test approach below:

/**
 * Test a console command.
 *
 * @return void
 */
public function test_console_command()
{
    $this->artisan('hackathon-starter:init')
         ->expectsQuestion('What type of project do you want to build?', 'PWA')
         ->expectsOutput('Initializing..')
         ->expectsQuestion('Please specify the type of PWA', 'pwa-on-fire')
         ->expectsOutput('Installing...')
         ->assertExitCode(0);
}

"Laravel 5.7 provides a better approach for testing artisan commands."

4. Multi-Lingual Support for Notifications

In Laravel 5.7, you can now send notifications in other locales, apart from the current language.

The Illuminate\Notifications\Notification class offers a locale method that can be invoked to set the preferred language.

  $user->notify((new EmailSent($email))->locale('zh'));
  Notification::locale('zh')->send($users, new EmailSent($email));

5. Paginator

By default, Laravel provides three links on each side of the primary paginator links.

In Laravel 5.7, there's a new option, onEachSide, to enable customization of the number of links displayed on both sides.

{{ $paginator->onEachSide(7)->links() }}

6. More Options for Guest Policies

By default, authorization gates and policies return false for guest visitors to your application. In this new release, you can now allow unauthenticated visitors to pass through authorization checks by declaring an "optional" type-hint or supplying a null default value for the user argument.

Gate::define('modify-sheet', function (?User $user, Sheet $sheet) {
    // ...
});

7. Optional Email Verification

Laravel 5.7 provides an optional email verification feature. An email_verified_at timestamp column has to be added to the user's table migration for this feature to work as intended.

If you want new users to verify their email, the User model needs to implement the MustVerfifyEmail interface.

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements MustVerifyEmail
{
    // ...
}

The newly registered users will receive an email containing a signed verification link. Once the user clicks the link, the app will automatically update the database and redirect the user to the intended location.

This feature also ships with a verified middleware for situations where you need to protect certain app routes from only verified members.

  'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,

8. Better Support for Development Errors

Joseph Silber submitted a PR that allows Laravel 5.7 to provide a clear and concise message when a non-existent method is called on a model.

9. URL Generator & Callable Syntax

Laravel 5.7 now supports callable array syntax for controller actions that generate URLs.

Before Laravel 5.7

$url = action('FoodController@index');

$url = action('FoodController@view', ['id' => 1]);

Now

$url = action([FoodController::class, 'index']);

$url = action([FoodController::class, 'view'], ['id' => 1]);

10. Laravel Nova

Taylor already announced that he was working on a project several months ago. The long awaited project called Laravel Nova has been released. Nova is a beautifully designed administration panel for Laravel. It offers support for filters, lenses, actions, queued actions, metrics, authorization, custom tools, custom cards, custom fields, etc.

Laravel Nova Laravel Nova

"As if Laravel 5.7 wasn't enough, @taylorotwell formally introduced @laravel_nova, a beautifully designed administration panel for Laravel."

Deprecations and Other Updates

  • The resources/assets directory has been flattened into resources.

Check out other Laravel 5.7 updates on GitHub.

Upgrading to Laravel 5.7

Laravel 5.7 requires PHP >= 7.1.3. And the estimated upgrade time from Laravel v5.6 is about ten to fifteen minutes.

Check out this comprehensive upgrade guide. However, if you don't want to be bothered about manually configuring and changing files for the upgrade, I recommend using Laravel Shift - A service that provides automated, instant Laravel upgrade services by an army of thorough bots and friendly humans.

Aside: Securing Laravel APIs with Auth0

Securing Laravel APIs with Auth0 is very easy and brings a lot of great features to the table. With Auth0, we only have to write a few lines of code to get:

Sign Up for Auth0

You'll need an Auth0 account to manage authentication. You can sign up for a free account here. Next, set up an Auth0 API.

Set Up an API

Go to APIs in your Auth0 dashboard and click on the "Create API" button. Enter a name for the API. Set the Identifier to a URL(existent or non-existent URL). The Signing Algorithm should be RS256.

Create API on Auth0 dashboard Create API on Auth0 dashboard

We're now ready to implement Auth0 authentication on our Laravel backend API.

Dependencies and Setup

Install the laravel-auth0 package via composer like so:

composer require auth0/login:"~5.0"

Generate the laravel-auth0 package config file like so:

php artisan vendor:publish

After the file is generated, it will be located at config/laravel-auth0.php. Ensure you replace the placeholder values with the authentic values from the Auth0 Admin Dashboard. Double check your values with laravel-auth0.

Your .env file should have the AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET and AUTH0_CALLBACK_URL values like so:

AUTH0_DOMAIN=kabiyesi.auth0.com
AUTH0_CLIENT_ID=xxxxxxxxxxxxxxxxxx
AUTH0_CLIENT_SECRET=xxxxxxxxxxxxxxxxx
AUTH0_AUDIENCE=http://mylaravelapi.com
AUTH0_CALLBACK_URL=null

Activate Provider and Facade

The laravel-auth0 package comes with a provder called LoginServiceProvider. Add this to the list of application providers.

// config/app.php
'providers' => array(
    // ...
    \Auth0\Login\LoginServiceProvider::class,
);

If you would like to use the Auth0 Facade, add it to the list of aliases.

// config/app.php

'aliases' => array(
    // ...
    'Auth0' => \Auth0\Login\Facade\Auth0::class,
);

The user information can now be accessed with Auth0::getUser(). Finally, you need to bind a class that provides a user (your app model user) each time the user is logged in or an access_token is decoded. You can use the Auth0UserRepository provided by this package or you can build your own class.

To use Auth0UserRepository, add the following lines to your app's AppServiceProvider:

// app/Providers/AppServiceProvider.php

public function register()
{

    $this->app->bind(
      \Auth0\Login\Contract\Auth0UserRepository::class, 
      \Auth0\Login\Repository\Auth0UserRepository::class
    );

}

Configure Authentication Driver

The laravel-auth0 package comes with an authentication driver called auth0. This driver defines a user structure that wraps the normalized user profile defined by Auth0. It doesn't actually persist the object but rather simply stores it in the session for future calls.

This is adequate for basic testing or if you don't have a requirement to persist the user. At any point you can call Auth::check() to determine if there is a user logged in and Auth::user() to retreive the wrapper with the user information.

Configure the driver in config/auth.php to use auth0.

// app/config/auth.php

// ...
'providers' => [
    'users' => [
        'driver' => 'auth0'
    ],
],

Secure API Routes

Your API routes are defined in routes/api.php for Laravel 5.3+ apps.

// routes/api.php

<?php

use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::get('/public', function (Request $request) {
  return response()->json(["message" => "Hello from a public endpoint! You don't need any token to access this URL..Yaaaay!"]);
});

Route::get('/wakanda', function (Request $request) {
  return response()->json(["message" => "Access token is valid. Welcome to this private endpoint. You need elevated scopes to access Vibranium."]);
})->middleware('auth:api');

Now, you can send a request to your protected endpoint which includes an access_token.

curl --request GET \
  --url http://localhost:8000/api/wakanda \
  --header 'authorization: Bearer <ACCESS TOKEN>'

Once a user hits the api/wakanda endpoint, a valid JWT access_token will be required before the resource can be released. With this in place, private routes can be secured.

More Resources

That's it! We have an authenticated Laravel API with protected routes. To learn more, check out the following resources:

Conclusion

Laravel 5.7 PHP framework came loaded with new features and significant improvements. And Nova is a product every Laravel developer should try out!

Have you upgraded to Laravel v5.7 yet? What are your thoughts? Let me know in the comments section! 😊

"Laravel 5.7 has been released! Learn what's new in the most popular PHP framework"