What's New in Laravel 5.5 LTS

Samuel Oloruntoba

Some time ago Taylor Otwell (the creator of Laravel) made an announcement that Laravel will get a major update every 6 months; well it's that time of the year again.

In this article we'll talk about some of the latest features in Laravel!

But First: Gotchas

5.5 is an LTS (Long-Term Support) release. This means that this version of Laravel will get support (bug fixes and the likes for many years).

PHP7+: If you still use any version lesser than 7 of PHP, please upgrade. Apart from the new developer features offered by PHP7 there's also speed improvements that will save you money. Tumblr recently upgraded to version 7 and quoting them

Almost immediately saw the latency drop by half, and the CPU load on the servers decrease at least 50%, often more. Not only were our servers serving pages twice as fast, they were doing it using half the amount of CPU resources.

If you need help migrating to the latest version of PHP you checkout the official migration guide or take a look at Migrating a PHP 5 app to PHP 7 Guide by Prosper Otemuyiwa. You can also hire me kayandrae07@gmail.com

Whoops

As a long time user of Laravel, I hated when whoops stack trace debugger was removed. Glad to see that it's back.

Some of the features of Whoops include:

  • Flexible, stack-based error handling
  • Stand-alone library with (currently) no required dependencies
  • Simple API for dealing with exceptions, trace frames & their data
  • Includes a pretty rad error page for your webapp projects
  • Includes the ability to open referenced files directly in your editor and IDE
  • Includes handlers for different response formats (JSON, XML, SOAP)
  • Easy to extend and integrate with existing libraries
  • Clean, well-structured & tested code-base

Blade::if() Directives

Blade received a new addition that simplifies custom if statements in your views. In our AppServiceProvider::boot() or a custom Service Provider ::boot() we can define something like this.

// make sure you import this class in service provider
use Illuminate\Support\Facades\Blade;

Blade::if('editor', function () {
    return auth()->check() && auth()->user()->isEditor();
});

After defining editor we can then move to our Blade files and do something like this.

@editor
    <a href="{{ route('post:approval') }}">Approve Posts</a>
@else
    <p>You shall not pass</p>
@endeditor

We can also pass arguments to our directives and we do that by:

Blade::if('editor', function ($level) {
    //
});

and it will look like this in our templates.

@editor('senior')
  <script src="fancy-editor.js"></script>
@endeditor

Auth and Guest Blade Directives

With the addition of Blade::if Laravel also included 2 new custom directives.

The first one is @auth which we use if a user is authenticated, and there's @guess which does the opposite.

Normally, to check an authenticated user we'd do

@if (auth()->check())
  <p>Welcome</p>
@endif

Now we just need to do

@auth
  <p>welcome</p>
@endauth

Fresh Migrations with migrate:fresh command

You might be wondering what the difference is between migrate:refresh and migrate:fresh. In the general sense of things, they do the same thing — with the difference being that migrate:fresh skips the down method of your migrations.

So if you run migrate:refresh the output might look like this.

$ php artisan migrate:refresh

Rolling back: 2014_10_12_100000_create_password_resets_table
Rolled back:  2014_10_12_100000_create_password_resets_table
Rolling back: 2014_10_12_000000_create_users_table
Rolled back:  2014_10_12_000000_create_users_table
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table

While running migrate:fresh will give you

$ php artisan migrate:fresh

Dropped all tables successfully.
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table

With this new command, you can skip the down() method of your migrations and just use the migrate:fresh command. This is particularly good news for developers that use foreign key relationships in the database.

DD and Dump Collections

Before 5.5 I used Macros by Spatie to dump collections for debugging.

With 5.5 comes Collection::dump() and Collection::dd(). If you've been using Laravel for a while, you can guess what these do. ::dump() outputs the result and continues processing while ::dd() "dumps and die".

collect([1,2,3])->map(function($i){
    return $i * 2;
})->reject(function($i){
    return $i < 3;
});

Take the above collection for example, we can do this:

collect([1,2,3])->map(function($i){
    return $i * 2;
})->dump()->reject(function($i){
    return $i < 3;
});

And we get:

Collection {#181 ▼
  #items: array:3 [▼
    0 => 2
    1 => 4
    2 => 6
  ]
}

Frontend Presets

Since 5.3 Laravel has shipped with optional Bootstrap and Vue.js scaffolding. The problem is that different people mean different tools of development. Since Laravel is not trying to force you to use a particular frontend framework, in this version more presets were added..

To use the React preset just run

php artisan preset react

To use the Bootstrap preset you can run

php artisan preset bootstrap

If you want to remove the presets you can also run

php artisan preset none

Package Auto-Discovery

Installing a Laravel Package requires at least these 2 or sometimes 3 steps:

Install the package:

composer require foo/bar

Register the provider in app.php:

[
  // ....
  Foo\Bar\ServiceProvider::class,
]

Optionally, register the Facade:

[
  // ....
  'Bar' => Foo\Bar\Facade::class,
]

One cool thing in 5.5 is packages can be automatically discovered by Laravel. So for package developers, you can add an extra section in your packages composer.json.

"extra": {
    "laravel": {
        "providers": [
            "Foo\\Bar\\ServiceProvider"
        ],
        "aliases": {
            "Bar": "Foo\\Bar\\Facade"
        }
    }
}

So when a developer installs your package composer require foo/bar they automatically have access to any aliases and the service providers are automatically registered.

Request Validation Method

In older versions of Laravel validating a request looked similar to this.

public function store()
{
    $data = $this->validate(request(), [
        'name' => 'required',
        'price' => 'required|numeric',
        'category_id' => 'numeric|exists:categories',
    ]);

    // no longer needed
    // $data = request()->only('name', 'price', 'category_id');

    return Product::create($data);
}

As you can see from the example above the request()->only() call is no longer needed as $this->validate() returns request()->only().

Custom Validation Rule Objects and Closure

Instead of using Validator::extend() (which we can still use) we can define a class that implements Illuminate\Contracts\Validation\Rule inteface or use a closure.

To create a new rule we use our Laravel handy helper artisan:

php artisan make:rule MyCustomRule

Our rules class will look like this.

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class MyCustomRule implements Rule
{
    public function passes($attribute, $value)
    {
        return $value > 10;
    }

    public function message()
    {
        return 'More please...';
    }
}

An example of using this validation rule looks like the following:

request()->validate([
    'files' => [new MyCustomRule],
    'more_cowbells' => [function ($attribute, $value, $fail) {
        if ($value <= 10) {
            $fail(':attribute needs more cowbell!');
        }
    }]
]);

The closure style takes the attribute and value, and a fail parameter that you call if the validation rule should fail. The closure is a nice way to experiment with custom validation before you extract it to a dedicated rule object, or for one-off custom validation needs.

Responsable Interfaces for Responses

A new interface called Responsable (Illuminate\Contracts\Support\Responsable) will allow objects to be converted to an HTTP response. This interface requires us to implement a toResponse() method that is rendered as an HTTP response.

Here's an example of what a class implementing this interface will look like.

use Illuminate\Contracts\Support\Responsable;

class ExampleObject implements Responsable
{
    public function __construct($name = null)
    {
        $this->name = $name;
    }

    public function status()
    {
        return 200;
    }

    public function toResponse()
    {
        if ($this->wantsJSON()) {
            return response(
                $this->name,
                $this->status()
            );
        }

        return view('index', ['name' => $this->name]);
    }
}

The Router class now checks for Responsable when preparing a response.

if ($response instanceof Responsable) {
    $response = $response->toResponse();
}

With this new addition, we can clean up our controllers even further as we can abstract the logic that makes the view possible.

Using this new Responsable we can return something like this from our routes.

Route::get('/', function () {
    return new ExampleObject('Chris Sevilleja');
})

vendor:publish Gets a Prompt

We are all familiar with those Laravel packages that after installation require you to publish their assets (pretty much all of them). Running vendor:publish on its own publishes every single asset, so to avoid that we have the option to use a tag or a provider so as to publish.

Now, there's a new way to do publish vendor assets. When you run php artisan vendor:publish you get a prompt and then choose the asset to publish.

Custom Exception Reporting

When a custom exception is thrown, we usually go to App\Exceptions\Handler::report() and listen for an instance of our exception. But with 5.5 we can define a report() method on our exception and Laravel will check every exception received by the exception handler for a report() method and trigger it if it exists.

This gives us finer control of how we handle exceptions as we can log it, send to our monitoring software, alert a developer.

The former method with time will lead to a really messy code base.

throw_if() and throw_unless()

throw_if() and throw_unless() are pretty much self-explanatory. Both functions accept a minimum of 2 parameters, the first one is a boolean and the second is the exception to throw.

throw_if() will throw an exception if the first condition is true while throw_unless() will throw an exception if the first parameter is false.

$foo = true;
throw_if($foo, new BarException('Foo is true'));
// or
throw_if($foo, BarException::class, 'Foo is true');

Here is the complete function for reference:

function throw_if($boolean, $exception, $message = '')
{
    if ($boolean) {
        throw (is_string($exception) ? new $exception($message) : $exception);
    }
}

For throw_unless()

$foo = false;
throw_unless($foo, new BarException('Foo is false'));
// or
throw_unless($foo, BarException::class, 'Foo is false');

Here's what the function looks like

function throw_unless($boolean, $exception, $message)
{
    if (! $boolean) {
        throw (is_string($exception) ? new $exception($message) : $exception);
    }
}

Render Mailables to the Browser

Mailables also got an update as they can now be rendered to the browser.

This makes sense for those people who like to create an archive of newletters or something. No more hacks are needed to get this to work.

Route::get('/demo', function () {
    return new App\Mail\UserWelcome();
});

Extras

Some features not covered in this article but still worth a mention.

  • Resource Classes allows us transform Eloquent models in a proper JSON data structure. We can also update our models to include a toArray() method, because when building an API that is intended for the public toArray() might be lacking.
  • Auto-Register Artisan Commands: You'll no longer be required to register your artisan commands. Instead Laravel will scan the commands directory and auto-register them. With this in mind you can create a command php artisan make:command MyCommand and automatically trigger it.
  • Route helpers: the route facade now comes with a few helpers of its own. Route::redirect() to perform a redirect. Route::view() to load a view.
  • RefreshDatabase Trait: All this does during testing is that it chooses the optimal path when migrating databases during tests.
  • withoutExceptionHandling() method: The base test case (Illuminate\Foundation\Testing\TestCase) inherits a withoutExceptionHandling() that allows you to disable exception handling for a test. It is a cool addition as we can run assertions on our exceptions instead of an exception handler taking over. Another reason is when an unexpected behaviour occurs you get to see the actual exception.
  • Support for Email Themes in Mailables
  • Improvements with the Default Error Views
  • Pivot Casting

In Closing

In case I missed anything you can check What's new in Laravel by Laracasts.

As usual, the docs are updated — including release notes, and upgrade guide.

Let us know about your favorite addition in the comments. Thank you.

Samuel Oloruntoba

32 posts

A web developer with an affinity for Laravel and Vue.js. Loves performance and advocates for it. Available for hire email freelance or otherwise