Laravel依赖性注入/IOC


Laravel dependency injection / IOC

我正在尝试集成到Xero API-我正在使用以下包装器:

https://github.com/drawmyattention/xerolaravel

我可以使用Facade方法访问API,但我真的很想解决依赖关系并正确地完成这一切,我仍在学习这些部分。

我已经按照指示,补充道:

DrawMyAttention'XeroLaravel'Providers'XeroServiceProvider::class

到我的app.php&在我的控制器内部,我正试图解决这个问题(我想是吗?)

我首先做以下事情:

use DrawMyAttention'XeroLaravel'Providers'XeroServiceProvider as Xero;
    private $xero;

public function __construct(XeroServiceProvider $xero)
{
    $this->xero = $xero;
}

即便如此,也会产生错误:

 BindingResolutionException in Container.php line 828:
 Unresolvable dependency resolving [Parameter #0 [ <required> $app ]] 
 in class Illuminate'Support'ServiceProvider

如果这是一个愚蠢的问题,我真的很抱歉——我对拉拉威尔的这方面没有太多涉猎。

服务提供商仅用于设置IOC的所有绑定和所有内容。正如您所提到的,您可以将它添加到config/app.php中,这样您就不再担心它了。这不是应该注入的类。

不幸的是,从代码来看,这个包并没有很好地为依赖项注入做好准备。这是服务提供商内部绑定之一的示例:

$this->app->bind('XeroPrivate', function () use ($config) {
    return new 'XeroPHP'Application'PrivateApplication($config);
});

使用此绑定,意味着您可以通过调用$private = app('XeroPrivate');从IOC中解析一个新的PrivateApplication实例。但是,由于PrivateApplication需要特殊的构造(构造函数中传递的配置),因此此设置对依赖项注入没有帮助。

绑定是为XeroPrivate设置的,但是,这个类不存在,这意味着你不能键入hint-it来注入它。您可能已经在config/app.php文件中添加了XeroPrivate作为别名,这将绕过XeroPrivate类不存在的问题,但这意味着注入了facade类(这就是别名所指向的),而不是PrivateApplication类。

为了能够正确地注入PrivateApplication类,您需要设置自己的绑定。您可以创建一个新的服务提供商,也可以将其添加到您的AppServiceProvider:中

$this->app->bind('XeroPHP'Application'PrivateApplication', function ($app) {
    return $app['XeroPrivate'];
});

您需要对PublicApplicationPartnerApplication:执行相同的操作

$this->app->bind('XeroPHP'Application'PublicApplication', function ($app) {
    return $app['XeroPublic'];
});
$this->app->bind('XeroPHP'Application'PartnerApplication', function ($app) {
    return $app['XeroPartner'];
});

有了这些绑定,您可以安全地将任何类注入到构造函数中,它们将得到正确的解决:

use XeroPHP'Application'PrivateApplication;
use XeroPHP'Application'PublicApplication;
use XeroPHP'Application'PartnerApplication;
public function __construct(PrivateApplication $xeroPrivate, PublicApplication $xeroPublic, PartnerApplication $xeroPartner)
{
    $this->xeroPrivate = $xeroPrivate;
    $this->xeroPublic = $xeroPublic;
    $this->xeroPartner = $xeroPartner;
}

当控制器被实例化时,它将看到它需要一个新的XeroPHP'Application'PrivateApplication实例,并且它将使用我们在上面创建的绑定从IOC中解析该实例(这反过来又从IOC解析XeroPublic对象)。它将对XeroPHP'Application'PublicApplicationXeroPHP'Application'PartnerApplication执行相同的操作。

其余的类不需要任何特殊的构造,因此不需要为它们创建自定义绑定。它们可以按原样注入:

use XeroPHP'Models'Accounting'Invoice;
use XeroPHP'Models'Accounting'Invoice'LineItem;
use XeroPHP'Models'Accounting'Contact;
use XeroPHP'Models'Accounting'BrandingTheme;
use XeroPHP'Models'Accounting'Attachment;
public function __construct(Invoice $xeroInvoice, LineItem $xeroLineItem, Contact $xeroContact, BrandingTheme $xeroBrandingTheme, Attachment $xeroAttachment)
{
    $this->xeroInvoice = $xeroInvoice;
    $this->xeroLineItem = $xeroLineItem;
    $this->xeroContact = $xeroContact;
    $this->xeroBrandingTheme = $xeroBrandingTheme;
    $this->xeroAttachment = $xeroAttachment;
}

当控制器被实例化时,它会看到它需要一个新的XeroPHP'Models'Accounting'Invoice实例,但由于IOC中没有这个类的绑定,它只需要new建立一个新实例并注入它。它将对上面显示的其余类执行相同的操作。

使用您指定的别名:

use DrawMyAttention'XeroLaravel'Providers'XeroServiceProvider as Xero;
class Foo {
    private $xero;
    public function __construct(Xero $xero)
    {
        $this->xero = $xero;
    }
}