Routes caching in L5

Laravel provides an easy way to cache your routes registration with the framework (not the response of the route) by running route:cache artisan command. If you get the following error:

  [LogicException]
  Unable to prepare route [/] for serialization. Uses Closure.

You can not cache routes that use Closure, as the docs specify:

If your application is exclusively using controller based routes, you may take advantageof Laravel's route cache.

Good bye filters, hello HTTP middleware

Filters are a great way to hook into your requests either before or after and Laravel has done a great work providing the tools we need however there was no clear convention on where to store objects (if you wanted to use objects instead of a callback) and their definition was in a filters.php file(kind of old school). In Laravel 5 filters have been replaced with HTTP Middleware which work in a similar way but more organised.

All middleware objects are stored in:

app/Http/Middleware/*

To create a new middleware you can use Laravel’s generators:

php artisan make:middleware OldMiddleware

The next step is to register the filter either globally (applies to all requests) or assign a key and use it per route, you can do both in:

app/Http/Kernel.php

To assign it to a specific route use “middleware” property:

Route::get('/', ['middleware' => 'MyMiddleware', function () {
    //
}]); 

To assign multiple middleware objects to a route define them in an array:

Route::get('/', ['middleware' => ['MyMiddleware', 'MySecondMiddleware'], function () {
    //
}]); 

When multiple middleware objects are registered for 1 route they are executed in order in which they were defined, in the example above “MyMiddleware” will be executed first.

To pass custom parameters to the middleware first define it in handle() method:


<?php namespace App\Http\Middleware;

use Closure;

class RoleMiddleware
{
  /**
    * Run the request filter.
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  \Closure  $next
    * @param  string  $param
    * @return mixed
    */
    public function handle($request, Closure $next, $param)
    {
       //
       return $next($request);
     }
  }

To pass params use “:” notation and “,” to separate multiple params:

Route::get('/', ['middleware' => 'MyMiddleware:param1,param2', function () {
    //
}]); 

Another important feature is “Terminable Middleware” which will be executed after the response has been sent, do not confuse with after filters from Laravel 4 which were executed after the request but before sending the response. To define it, add “terminate()” method to a middleware object:


<?php namespace App\Http\Middleware;

use Closure;

class RoleMiddleware
{
  /**
    * Run the request filter.
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  \Closure  $next
    * @param  string  $param
    * @return mixed
    */
    public function handle($request, Closure $next, $param)
    {
       //
       return $next($request);
     }

    public function terminate($request, $response)
    {
        // Log something?
    }
  }

PSR-4 and App name in Laravel 5

Last year we talked about PSR-4 in Laravel and how we can use it to structure our projects under 1 namespace, L5 now supports it out of the box, the whole project is under App namespace (including the controllers).

If you want to change your App name simply run this artisan command:

php artisan app:name ProjectName

And Laravel will rename all the necessary files.

Traits in PHP

If you worked with abstract objects before, you are aware of the single inheritance limitation, traits fix this in a very elegant way to allow us to write re-usable code.

Creating traits

Traits are created using the trait keyword:


trait MyTrait {

    function my_function()
    {
       echo 'My first trait';
    }

}

Using traits

To add a trait to a class, use the use keyword within the class:


class MyClass {

    use MyTrait;

}

That’s it! now you have all the trait’s methods available, to use multiple traits you can declare them on the same line separating them with a comma:


class MyClass {
    use MyTrait, MySecondTrait;

}

Note: traits can’t be instantiated.