1
votes

I am trying to make custom Facades for my Laravel 5.1.17 application. I have followed the Laravel documentation as well as this tutorial step by step and indeed I was able to create a custom Facade for my custom service.

However, all of a sudden it broke. The error message I get is:

FatalErrorException in Facade.php line 207:
Call to undefined method App\Facades\BookLookUp::test()

In other words, my Facade is not getting bound, and instead Laravel is looking for the test() method within my intermediary BookLookUp extends Facade class rather than my intended service BookLookUp class.

What is very strange is that it was working perfectly fine, and then it just stopped working. What I did which seems to have made it break was I tried to add another Facade by duplicating my relevant files and just switching the names, but somehow my original Facade which remained untouched stopped working as well.

Another related oddity was I tried to recreate from scratch all the necessary files for my Facade and it worked, good as new. Then I went and renamed the Facade and corresponding classes/files, and wham it broke again.

Thus it seems manipulating the folder somehow breaks things, but this makes no sense. Is there a reason my Facades are not working anymore?

Below are my relevant files:

App/Services/BookLookUp.php

<?php

namespace App\Services;

class BookLookUp {
    public function test()
    {
        return "foo";
    }
}

App/Facades/BookLookUp.php

<?php

namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class BookLookUp extends Facade
{
    protected static function getFacadeAccessor() 
    { 
        return 'BookLookUp'; 
    }
}

App/Providers/BookLookUpServiceProvider.php

<?php

namespace App\Providers;

use App\Services\BookLookUp;
use Illuminate\Support\ServiceProvider;

class BookLookUpServiceProvider extends ServiceProvider
{
    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = true;

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

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('BookLookUp', function() {
            return new BookLookUp();
        });
    }

     /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return ['App\Services\BookLookUp'];
    }
}

App/Http/Routes.php

<?php

Route::get('/', function() {
    return BookLookUp::test();
});
1

1 Answers

1
votes

The problem was that I set protected $defer = true; but my provides() method was not returning the correct value; Instead, the correct return value would simply be return ['BookLookUp'], just as the register method returns a BookLookUp.

As for why things changed upon manipulating files, this is due to composer. Bindings are reset when calling composer update so before I had manipulated any files it was never called and appeared to be working. Once it was called it attempted to register the bindings I now provided except that I had an error in my method like I described before, so it was never able to correctly locate my BookLookUp class.