1
votes

I am trying to make my own custom Facade and register is with a custom service container and finally creating a custom alias for this facade.

I am not sure what part is not working, maybe there is a problem with the service container registering or maybe with the alias?

Let's start with my facade:

/**
 *
 * @see \App\Library\Facades\ViewWrapper\CustomView
*/
class CustomViewFacade extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'customview';
    }
}

My CustomView class with the logic and the show function

namespace App\Library\Facades\ViewWrapper;

...

class CustomView
{
    public function show(...) { ... }

    ...
} 

My CustomViewServiceProvider

namespace App\Providers;

...  

class CustomViewServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(CustomViewFacade::class);
        $this->app->alias(CustomViewFacade::class, 'customview');
    }
}

How I register the provider in the config\app.php

App\Providers\CustomViewServiceProvider::class,

How I create the alias in the config\app.php

'CustomView' => App\Library\Facades\ViewWrapper\CustomViewFacade::class

In my controller I use the facade like this:

use CustomView;

...

public function show(ImageRequest $imagerequest)
{
    return CustomView::show(...);
}

I get the following error in the controller:

Class 'CustomView' not found

What am I doing wrong here?

EDIT

After clearing config and composer autoload dump I get the following error:

Call to undefined method App\Library\Facades\ViewWrapper\CustomViewFacade::show()

2
please try php artisan cache:clear and composer dumpautoload -oparastoo amini

2 Answers

3
votes

I think you haven't quite clearly understood how Facades work. They are just an easy way to access your services without having to deal with dependency injection. I'm not a fan of this methodology, but here's how you do it properly.

  1. You need to bind your actual service to the container, not the facade. The facade is almost just a symbolic link to your service within the container.
  2. You need to import the actual service, not the facade. Laravel will automatically bind your dependency in the type-hinted variable, thanks to its behind the scenes magic.

Use:

use App\Library\Facades\ViewWrapper\CustomView;

(small note: your namespace here should be your service's namespace, be aware to not mix up the semantic between facade and service. The service contains the logic, the facade is just an accessor to a service that is already injected. This is important!!)

Instead of:

use CustomView;

It should solve the issue.

Also, I'd suggest you do define how the class should be constructed and injected in the Service Container by using a Closure in the bootstrap function.

class CustomViewServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(CustomView::class, function () {
            return new CustomView(...);
        );
    }
}

Also, the alias function is not necessary in your case. It'd simply allow you to access the service by using the customview key in the Service Container.

Just define the Facade in your config/app.php file.

Another small suggestion: use PHP 7 class selectors instead of strings in your facade accessor definition. For example: CustomView::class intead of customview. It makes your code neater and easier to read.

1
votes

Please run below command and check:

php artisan config:cache

php artisan cache:clear