Laravel 绑定的用途和目的是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/49348681/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is a usage and purpose of Laravel's binding?
提问by Andrii H.
I cannot understand a point of Laravel's binding system. I know what does dependency injection mean. And it can work even without that weird "bindings", right? I saw in documentation, that binding can return a new object. Why and when I have to use that? Please, explain not very complicated, because I've read documentation and I could not understand the use and the purpose of that bindings. Thanks.
我无法理解 Laravel 绑定系统的一点。我知道依赖注入是什么意思。即使没有那种奇怪的“绑定”,它也可以工作,对吧?我在文档中看到,绑定可以返回一个新对象。为什么以及何时必须使用它?请解释不是很复杂,因为我已经阅读了文档,但我无法理解该绑定的用途和目的。谢谢。
回答by Risan Bagja Pradana
And it can work even without that weird "bindings", right?
即使没有那种奇怪的“绑定”,它也可以工作,对吧?
Not really. Sure it can work just fine if the required dependencies are simple to instantiate. Let's say you have this simple class Foo
stored in app
directory:
并不真地。如果所需的依赖项易于实例化,它当然可以正常工作。假设您将这个简单的类Foo
存储在app
目录中:
<?php
namespace App;
class Foo
{
public function hello()
{
return 'Hello World';
}
}
You can type hinted this class without binding it first in the container. Laravel will still be able to resolve this class. Let's say you type-hinted it like this in the routes:
您可以键入hinted 此类,而无需先将其绑定到容器中。Laravel 仍然可以解析这个类。假设您在路由中这样输入提示:
Route::get('/foo', function (App\Foo $foo) {
return $foo->hello(); // Hello World
});
We can even go further, let's say this Foo
class required another simple class Bar
. Our Bar
class looks like this:
我们甚至可以更进一步,假设这个Foo
类需要另一个简单的类Bar
。我们的Bar
班级是这样的:
<?php
namespace App;
class Bar
{
public function hello()
{
return 'bar';
}
}
And our Foo
class looks like this now:
我们的Foo
类现在看起来像这样:
<?php
namespace App;
class Foo
{
public function __construct(Bar $bar)
{
$this->bar = $bar;
}
public function hello()
{
return $this->bar->hello();
}
}
Will Laravel be able to resolve the type-hinted Foo
class now? YES! Laravel will still be able to resolve this Foo
class.
LaravelFoo
现在能够解析类型提示类吗?是的!Laravel 仍然可以解析这个Foo
类。
Now the issue will come in when our Foo
class needs slightly more complex dependencies that need to be configured. Imagine that our Foo
class simply need the name of our application. Sure you can simply use config('app.name')
within the class's method, but imagine that this can be an HTTP client that requires a configuration array to instantiate.
现在,当我们的Foo
类需要配置稍微复杂的依赖项时,问题就会出现。想象一下,我们的Foo
类只需要应用程序的名称。当然,您可以简单地config('app.name')
在类的方法中使用,但是想象一下,这可以是一个需要配置数组来实例化的 HTTP 客户端。
<?php
namespace App;
class Foo
{
public function __construct($appName)
{
$this->appName = $appName;
}
public function hello()
{
return "Hello {$this->appName}";
}
}
Will Laravel be able to solve this class now? NOPE. Service Containerto the rescue! You can teach Laravel how to resolve this Foo
class by binding it in service container. You can define the binding within the register
method on app\Providers\AppServiceProvider.php
file:
Laravel 现在能解决这个类了吗?不。服务容器来救援!你可以Foo
通过在服务容器中绑定它来教 Laravel 如何解析这个类。您可以register
在app\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']);
});
}
And sometimes, you don't want multiple instances to be created. Like our Foo
class for instance, there's no need for multiple instances for this kind of class. In this case, we can bind it with singleton method.
有时,您不希望创建多个实例。就像我们的Foo
类一样,这种类不需要多个实例。在这种情况下,我们可以使用单例方法绑定它。
$this->app->singleton(\App\Foo::class, function ($app) {
return new \App\Foo($app->config['app.name']);
});
More Important Usage
更重要的用法
But the more important usage of this service container is that we can bind an interface to it's implementation. Let's say we have this PaymentProcessorInterface
with pay
method:
但是这个服务容器更重要的用途是我们可以将一个接口绑定到它的实现。假设我们有这个PaymentProcessorInterface
withpay
方法:
<?php
namespace App;
interface PaymentProcessorInterface
{
public function pay();
}
Then we have the implementation of this interface named StripeProcessor
:
然后我们有这个接口的实现,名为StripeProcessor
:
<?php
namespace App;
class StripeProcessor implements PaymentProcessorInterface
{
public function pay()
{
return 'pay with stripe';
}
}
With service container, we can bind the PaymentProcessorInterface
to StripeProcessor
class:
使用服务容器,我们可以绑定PaymentProcessorInterface
toStripeProcessor
类:
$this->app->bind(\App\PaymentProcessorInterface::class, function () {
return new \App\StripeProcessor();
});
We can then type-hinted PaymentProcessorInterface
within our code:
然后我们可以PaymentProcessorInterface
在我们的代码中进行类型提示:
Route::get('/pay', function (App\PaymentProcessorInterface $paymentProcessor) {
return $paymentProcessor->pay(); // pay with stripe
});
This way we can easily swap the PaymentProcessorInterface
implementation. Let's say we want to change the payment processor to Paypal then we have this PaypalProcessor
class.
这样我们就可以轻松地交换PaymentProcessorInterface
实现。假设我们想将支付处理器更改为 Paypal,那么我们就有了这个PaypalProcessor
类。
<?php
namespace App;
class PaypalProcessor implements PaymentProcessorInterface
{
public function pay()
{
return 'pay with paypal';
}
}
All we have to do is update the binding:
我们所要做的就是更新绑定:
$this->app->bind(\App\PaymentProcessorInterface::class, function () {
return new \App\PaypalProcessor();
});
Hope this gives you some ideas.
希望这能给你一些想法。