Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Set Up Facades in Laravel 5.2 (outside of /app)

I'm asking/answering because I have had so much trouble getting this working and I'd like to show a step-by-step implementation.

References:

  • https://laravel.com/docs/5.0/facades#creating-facades
  • http://www.n0impossible.com/article/how-to-create-facade-on-laravel-51
like image 675
Martin Avatar asked Feb 25 '16 22:02

Martin


1 Answers

This may not be the only way to implement facades in Laravel 5, but here is how I did it.

We're going to create a custom Foo facade available in the Foobar namespace.

1. Create a custom class

First, for this example, I will be creating a new folder in my project. It will get its own namespace that will make it easier to find.

In my case the directory is called Foobar:

enter image description here

In here, we'll create a new PHP file with our class definition. In my case, I called it Foo.php.

<?php
// %LARAVEL_ROOT%/Foobar/Foo.php

namespace Foobar;


class Foo
{
    public function Bar()
    {
        return 'got it!';
    }
}

2. Create a facade class

In our fancy new folder, we can add a new PHP file for our facade. I'm going to call it FooFacade.php, and I'm putting it in a different namespace called Foobar\Facades. Keep in mind that the namespace in this case does not reflect the folder structure!

<?php
// %LARAVEL_ROO%/Foobar/FooFacade.php

namespace Foobar\Facades;


use Illuminate\Support\Facades\Facade;

class Foo extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'foo'; // Keep this in mind
    }
}
  • Bear in mind what you return in getFacadeAccessor as you will need that in a moment.

Also note that you are extending the existing Facade class here.

3. Create a new provider using php artisan

So now we need ourselves a fancy new provider. Thankfully we have the awesome artisan tool. In my case, I'm gonna call it FooProvider.

php artisan make:provider FooProvider

Bam! We've got a provider. Read more about service providers here. For now just know that it has two functions (boot and register) and we will add some code to register. We're going to bind our new provider our app:

$this->app->bind('foo', function () {
    return new Foo; //Add the proper namespace at the top
});

So this bind('foo' portion is actually going to match up with what you put in your FooFacade.php code. Where I said return 'foo'; before, I want this bind to match that. (If I'd have said return 'wtv'; I'd say bind('wtv', here.)

Furthermore, we need to tell Laravel where to find Foo!

So at the top we add the namespace

use \Foobar\Foo;

Check out the whole file now:

<?php
// %LARAVEL_ROOT%/app/Providers/FooProvider.php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Foobar\Foo;

class FooProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('foo', function () {
            return new Foo;
        });
    }
}
  • Make sure you use Foobar\Foo and not Foobar\Facades\Foo - your IDE might suggest the wrong completion.

4. Add our references to config/app.php

Now we have to tell Laravel we're interested in using these random files we just created, and we can do that in our config/app.php file.

  1. Add your provider class reference to 'providers': App\Providers\FooProvider::class

  2. Add your facade class reference to 'aliases': 'Foo' => Foobar\Facades\Foo::class

Remember, in aliases, where I wrote 'Foo', you will want to put the name you want to reference your facade with there. So if you want to use MyBigOlFacade::helloWorld() around your app, you'd start that line with 'MyBigOlFacade' => MyApp\WhereEverMyFacadesAre\MyBigOlFacade::class

5. Update your composer.json

The last code change you should need is to update your composer.json's psr-4 spaces. You will have to add this:

    "psr-4": {
        "Foobar\\" : "Foobar/",
        // Whatever you had already can stay
    }

Final move

Okay so now that you have all that changed, the last thing you need is to refresh the caches in both composer and artisan. Try this:

composer dumpautoload
php artisan cache:clear

Usage & A Quick Test:

Create a route in app/routes.php:

Route::get('/foobar', 'FooBarController@testFoo');

Then run

php artisan make:controller FooBarController

And add some code so it now looks like this:

<?php

namespace App\Http\Controllers;

use Foobar\Facades\Foo;

use App\Http\Requests;

class FooBarController extends Controller
{
    public function testFoo()
    {
        dd(Foo::Bar());
    }
}

You should end up with the following string:

enter image description here


Troubleshooting

  • If you end up with and error saying it cannot find the class Foobar\Facades\Foo, try running php artisan optimize
like image 197
Martin Avatar answered Sep 21 '22 00:09

Martin