Properly inject AuthManager?

橙三吉。 提交于 2019-12-11 12:24:01

问题


I am using jwt-auth library, which injects AuthManager using type-hinting:

use Illuminate\Auth\AuthManager;
class Basic extends Authorization
{

public function __construct(AuthManager $auth, $identifier = 'email')
    {
        $this->auth = $auth;
        $this->identifier = $identifier;
    }

The problem is that if I used the middleware jwt.auth:

app('Dingo\Api\Routing\Router')->version('v1', ['middleware' => ['jwt.auth'] , 'prefix' => 'api', 'providers' => ['jwt']], function ($api) {
    $api->get('protected', function () {

       $token = JWTAuth::getToken();
       return $token;
    });
});

I get this error:

{"message":"Unresolvable dependency resolving [Parameter #0 [ <required> $app ]] in class Illuminate\\Auth\\AuthManager","status_code":500,"debug":{"line":839,"file":"\/share\/vendor\/illuminate\/container\/Container.php","class":"Illuminate\\Contracts\\Container\\BindingResolutionException"

So, the question is, how to properly inject the AuthManager ? why $app was not resolved?


回答1:


Try injecting AuthManager in your bootstrap/app.php file:

/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
|
| Here we will register all of the application's service providers which
| are used to bind services into the container. Service providers are
| totally optional, so you are not required to uncomment this line.
|
*/

$app->register(App\Providers\AppServiceProvider::class);
$app->register(App\Providers\EventServiceProvider::class);

// Injecting goes here
$app->singleton(Illuminate\Auth\AuthManager::class, function ($app) {
    return $app->make('auth');
});

Explanation

We know that Illuminate\Auth\AuthManager will be resolved automatically if we run Illuminate\Auth\AuthServiceProvider. See:

Illuminate\Auth\AuthServiceProvider@registerAuthenticator

So, we must run this service provider before we want to use AuthManager. But Lumen is slightly different. I see that Illuminate\Auth\AuthManager isn't registered yet in:

Laravel\Lumen\Application::$availableBindings

Which is it's a hack to make Lumen run faster when the container wants to resolved the resource, see:

Laravel\Lumen\Application@make

So, basically, if you want to resolve Illuminate\Auth\AuthManager class and it's dependency, you may register it's class bindings first before you use it.

Update

We know that

Laravel\Lumen\Application::$availableBindings

property is in public visibility, so this works too:

/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
|
| Here we will register all of the application's service providers which
| are used to bind services into the container. Service providers are
| totally optional, so you are not required to uncomment this line.
|
*/

$app->register(App\Providers\AppServiceProvider::class);
$app->register(App\Providers\EventServiceProvider::class);

$app->availableBindings['Illuminate\Auth\AuthManager'] = 'registerAuthBindings';
$app->alias('auth', 'Illuminate\Auth\AuthManager');

Update 2

I understand that there's lot of problems if we want to implements JWT Authentication in Lumen with this library. So, I make a bootstrapped (clean start) Lumen Application that integrated well with this library. Please check out my repo. I'll add explanation about which one and why we should change the code later. Cheers.




回答2:


I experienced this with SessionManager with the same unresolvable $app variable when registering the existing Laravel SessionServiceProvider.

After reading @krisanalfa's answer, I tried to peek at the values of $availableBindings which can be found in Application.php and it looks like this:

public $availableBindings = [
      'auth' => 'registerAuthBindings',
      'auth.driver' => 'registerAuthBindings',
      'Illuminate\Auth\AuthManager' => 'registerAuthBindings',

      'Illuminate\Contracts\Cache\Factory' => 'registerCacheBindings',
      'Illuminate\Contracts\Cache\Repository' => 'registerCacheBindings',
      ....
];

The value of each keys represents the methods that is going to be used to load the implementations which is also inside the Application.php.

If you need to load the configuration and register the binding:

protected function registerAuthBindings()
{
    $this->singleton('auth', function () {
        return $this->loadComponent('auth', 'Illuminate\Auth\AuthServiceProvider', 'auth');
    });

    $this->singleton('auth.driver', function () {
        return $this->loadComponent('auth', 'Illuminate\Auth\AuthServiceProvider', 'auth.driver');
    });

   ...
}

But if the service doesn't need any configuration, you just register it like:

protected function registerEventBindings()
{
    $this->singleton('events', function () {
        $this->register('Illuminate\Events\EventServiceProvider');

        return $this->make('events');
    });
}

Source at the time of this writing: https://github.com/laravel/lumen-framework/blob/5.8/src/Application.php

Hope this helps others in the future. This took me lots of hours.



来源:https://stackoverflow.com/questions/35826585/properly-inject-authmanager

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!