Load Service Providers & Aliases for Local/Development Environment Only in Laravel 5

In laravel, there are times when you need to install packages only for your local or development environment for debugging and testing purposes.

Even if you specify those packages in require-dev section of your composer.json file, you still need to add the service providers and aliases in the config/app.php file. Without that, it won’t work.

With Laravel 5, you can easily load service providers based on your environment. In this example, we’ll install the barryvdh/laravel-debugbar package which displays a pretty debug information during testing of your application.

1. Add the package to your composer.json file

"require-dev": {
    "fzaninotto/faker": "~1.4",
    "mockery/mockery": "0.9.*",
    "phpunit/phpunit": "~4.0",
    "phpspec/phpspec": "~2.1",
    "barryvdh/laravel-debugbar": "^2.0"
}

Save the file, and do a composer update.

composer update

 

2. Create a new ServiceProvider called LocalServiceProvider

// file: app/Providers/LocalServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class LocalServiceProvider extends ServiceProvider
{

    protected $providers = [
        'Barryvdh\Debugbar\ServiceProvider'
    ];
    protected $aliases = [
        'Debugbar' => 'Barryvdh\Debugbar\Facade'
    ];
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //register the service providers for local environment
        if ($this->app->isLocal() && !empty($this->providers)) {
            foreach ($this->providers as $provider) {
                $this->app->register($provider);
            }
            //register the alias
            if (!empty($this->aliases)) {
                foreach ($this->aliases as $alias => $facade) {
                    $this->app->alias($alias, $facade);
                }
            }
        }

    }
}

 

3. Add the new ServiceProvider to the config/app.php service provider list

/*
 * Application Service Providers...
 */
App\Providers\AppServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\Providers\LocalServiceProvider::class,

 

To ensure laravel detects the correct environment, you have to make sure you are specifying the correct environment in your .env file.

APP_ENV=local

Now whenever you have packages you want to use only in your local environment, you can append their service providers to the $providers array and their aliases to the $aliases array. This way, they don’t get loaded unnecessarily in your production environment.

Redirect all Laravel 5 FormRequest Authorize Failures to a Route/URL

Form validation and other checks have become very easy to implement in Laravel 5 with the help of Form Requests.

Every Form Request should have an authorize() and a rules() method.

You can do ownership and other access checks in the authorize() method, and in the rules() method, you return an array with the rules for form validation. By default, if the method authorize fails/returns false, Laravel sends a 403 forbidden response.

Instead of that, when the authorize fails, you can redirect to an error page with a custom error message.

<?php namespace App\Http\Requests;

use App\Post;

class PostFormRequest extends Request {

    protected $post;
    protected $error;

    /**
     * Check if post belongs to user
     */
    public function authorize()
    {
        $this->post = Post::findOrFail($this->input('id', 0); //default ID to 0, if not sent through form.
        if ($this->user->id !== $this->post->user_id) {
             $this->error = 'Sorry, you do not have permission to edit this post';
             return false;
        }
        return true;
    }
    /**
     * This method will be invoked if authorize() fails
     */
    public function forbiddenResponse()
    {
        return redirect('error')->with('error_message', $this->error);
    }
    /**
     * Validation rules
     */
    public function rules()
    {
        return [
            'title' => 'required',
            'content' => 'required'
        ];
    }
}

With the above code, if a request fails the authorize() method, it’ll be redirected to www.domain.com/error with an error message.

However, if you have multiple Form Requests, its better to put all the code in the parent Request (app/Http/Requests/Request.php) class.

<?php namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

abstract class Request extends FormRequest {
    //A generic error message, can be overridden in the sub class
    protected $error = 'An error occurred';

    public function forbiddenResponse()
    {
        return redirect('dashboard')->with('msg_error', $this->error);
    }
}