Laravel绑定的用法和目的是什么?

2022-08-30 17:24:27

我无法理解Laravel的绑定系统的一点。我知道依赖注入是什么意思。即使没有奇怪的“绑定”,它也可以工作,对吧?我在文档中看到,绑定可以返回一个新对象。为什么以及何时必须使用它?请解释一下不是很复杂,因为我读过文档,我无法理解该绑定的用法和目的。谢谢。


答案 1

即使没有奇怪的“绑定”,它也可以工作,对吧?

没有。当然,如果所需的依赖项易于实例化,它可以正常工作。假设您将这个简单的类存储在目录中:Fooapp

<?php

namespace App;

class Foo
{
    public function hello()
    {
        return 'Hello World';
    }
}

可以键入 hinted 此类,而无需先在容器中绑定它。Laravel 仍然能够解析这个类。假设您在路由中像这样键入提示:

Route::get('/foo', function (App\Foo $foo) {
    return $foo->hello(); // Hello World
});

我们甚至可以更进一步,假设这个类需要另一个简单的类。我们的类看起来像这样:FooBarBar

<?php

namespace App;

class Bar
{
    public function hello()
    {
        return 'bar';
    }
}

我们的类现在看起来像这样:Foo

<?php

namespace App;

class Foo
{
    public function __construct(Bar $bar)
    {
        $this->bar = $bar;
    }

    public function hello()
    {
        return $this->bar->hello();
    }
}

Laravel 现在能够解析类型提示类吗?是的!Laravel 仍然能够解析这个类。FooFoo

现在,当我们的类需要稍微复杂一些需要配置的依赖项时,问题就会出现。想象一下,我们的类只需要应用程序的名称。当然,您可以简单地在类的方法中使用,但想象一下,这可以是一个HTTP客户端,需要配置数组来实例化。FooFooconfig('app.name')

<?php

namespace App;

class Foo
{
    public function __construct($appName)
    {
        $this->appName = $appName;
    }

    public function hello()
    {
        return "Hello {$this->appName}";
    }
}

Laravel现在能够解决这个类吗?不。服务容器来救援!你可以教 Laravel 如何通过在服务容器中绑定它来解析这个类。您可以在文件上的方法中定义绑定:Fooregisterapp\Providers\AppServiceProvider.php

public function register()
{
    $this->app->bind(\App\Foo::class, function ($app) {
        // Pass the application name
        return new \App\Foo($app->config['app.name']);
    });
}

有时,您不希望创建多个实例。例如,就像我们的类一样,这种类不需要多个实例。在这种情况下,我们可以用单例方法绑定它。Foo

$this->app->singleton(\App\Foo::class, function ($app) {
    return new \App\Foo($app->config['app.name']);
});

更重要的用法

但此服务容器更重要的用法是,我们可以将接口绑定到它的实现中。假设我们用这个方法:PaymentProcessorInterfacepay

<?php

namespace App;

interface PaymentProcessorInterface
{
    public function pay();
}

然后我们有这个接口的实现,命名为:StripeProcessor

<?php

namespace App;

class StripeProcessor implements PaymentProcessorInterface
{
    public function pay()
    {
        return 'pay with stripe';
    }
}

使用服务容器,我们可以将 to 类绑定到:PaymentProcessorInterfaceStripeProcessor

$this->app->bind(\App\PaymentProcessorInterface::class, function () {
    return new \App\StripeProcessor();
});

然后,我们可以在代码中键入提示:PaymentProcessorInterface

Route::get('/pay', function (App\PaymentProcessorInterface $paymentProcessor) {
    return $paymentProcessor->pay(); // pay with stripe
});

通过这种方式,我们可以轻松地交换实现。假设我们要将支付处理器更改为PayPal然后我们有这个类。PaymentProcessorInterfacePaypalProcessor

<?php

namespace App;

class PaypalProcessor implements PaymentProcessorInterface
{
    public function pay()
    {
        return 'pay with paypal';
    }
}

我们所要做的就是更新绑定:

$this->app->bind(\App\PaymentProcessorInterface::class, function () {
    return new \App\PaypalProcessor();
});

希望这能给你一些想法。


答案 2

推荐