问题
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