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