执行依赖注入时,Laravel 5.6“无法解析的依赖关系解析...”

时间:2018-06-02 19:42:41

标签: php laravel laravel-5

我试图通过中间件将一个类绑定到容器中,它似乎不起作用,因为我绑定的类在构造函数中收到了2个参数,但它们无法识别。

我收到以下错误消息:“类App \ Services \ Factureaza 中无法解析的依赖项解析[参数#0 [$ base_url]]。”

这是中间件:

<?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);
    }
}

Factureaza课程如下所示:

<?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;
    }
}

当我尝试解析控制器中的依赖项时,我收到此错误:

<?php

class InvoicesController extends Controller
{
    protected $api;

    public function __construct()
    {
        $this->api = resolve('App\Services\Factureaza');
    }
}

1 个答案:

答案 0 :(得分:1)

您的绑定应该在服务提供商中。您拥有的中间件直到Controller实例化后才会运行。此时没有单个容器绑定到容器。绑定在生命周期中太晚,无法在那里为控制器分配路由。

Laravel在运行路由中间件之前实例化Controller。它需要这样做才能收集控制器可以在其构造函数中定义的中间件来构建中间件堆栈。

<强>更新

一些可能的在没有重构的情况下解决(没有测试):

1)使用方法注入而不是尝试在构造函数中获取实例:

public function show(Factureaza $factureaza, ...)

2)使用控制器构造函数中定义的闭包中间件来获取实例并进行分配。

public function __construct()
{
    $this->middleware(function ($request, $next) {
        $this->api = resolve(Factureaza::class);
        return $next($request);
    });
}

希望设置单例所需信息的中间件在此控制器中间件之前运行。

3)让中间件在控制器上为你设置这个API ...需要向控制器添加一个方法来获取这些信息。 您可以访问路径的控制器,因为它已经被实例化并分配给路径。

$request->route()->getController()->setApi(...);