问题
I am trying to bind a class into the container via a middleware and it doesn't seem to work because the class that I am binding recieved 2 parameters in the constructor and they aren't recognised.
I am getting the following error message: "Unresolvable dependency resolving [Parameter #0 [ $base_url ]] in class App\Services\Factureaza".
Here is the middleware:
<?php
namespace App\Http\Middleware;
use App\Services\Factureaza;
use Closure;
class InitializeInvoiceProvider
{
public function handle($request, Closure $next)
{
app()->singleton(Factureaza::class, function () {
// get settings by calling a custom helper function
$settings = json_decode(get_setting('invoicing_provider_settings'), true);
$api_url = isset($settings['url']) ? $settings['url'] : null;
$api_key = isset($settings['key']) ? $settings['key'] : null;
return new Factureaza($api_url, $api_key);
});
return $next($request);
}
}
The Factureaza class looks like this:
<?php
namespace App\Services;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\RequestException;
class Factureaza
{
protected $client;
protected $base_url;
protected $api_key;
public function __construct($base_url, $api_key)
{
$this->client = new GuzzleClient([
'base_uri' => $base_url,
'verify' => false,
'auth' => [$api_key, 'x'],
]);
$this->base_url = $base_url;
$this->api_key = $api_key;
}
}
I am getting this error when I am trying to resolve the dependency in my controller:
<?php
class InvoicesController extends Controller
{
protected $api;
public function __construct()
{
$this->api = resolve('App\Services\Factureaza');
}
}
回答1:
Your binding should be in a Service Provider. The middleware you have isn't ran until after that Controller has been instantiated. There is no singleton bound to the container at this point. The bind is too late in the life cycle to be able to be there for a controller that a route is being dispatched to.
Laravel instantiates the Controller before it runs the route middleware. It needs to do this to be able to gather the middleware that a controller can define in its constructor to build the middleware stack.
Update:
Some Possible work arounds (did not test) without refactoring:
1) Use method injection instead of trying to get an instance in the constructor:
public function show(Factureaza $factureaza, ...)
2) Use a closure middleware defined in the constructor of the controller to get an instance and assign it.
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->api = resolve(Factureaza::class);
return $next($request);
});
}
Hopefully the middleware that sets the information that the singleton needs has ran before this controller middleware.
3) Have a middleware set this api on the controller for you ... would require adding a method to the controllers to take this information. You have access to the controller for the route as it has already be instantiated and assigned to the Route.
$request->route()->getController()->setApi(...);
来源:https://stackoverflow.com/questions/50660549/laravel-5-6-unresolvable-dependency-resolving-when-doing-dependency-injecti