服务容器是Laravel必要了解的一个概念。服务容器是告诉Laravel如何构造一个class或者对象,使得Laravel可以从此配置你的class或者对象。官网上说服务容器是一个非常强大的管理类依赖和依赖注入的工具。其实我们看下例子可以更容易地理解它。
我们知道Laravel可以利用添加namespace的方式引入外部类文件。但是如果我们创建了一个控制器,我们引入的时候可能需要实例化一下。
但是如果是在laravel内部了,那么我们可以直接以依赖注入的方式注入到控制器的某个方法里。例如:
namespace App\Http\Controllers;
use App\Handlers\PaymentGateway;
class PayOrderController extends Controller {
public function store(PaymentGateway $paymentgateway){
}
}
我们设想一下如果PaymentGateway这个类没有构造方法和需要传入一些变量的话,我们可以直接直接用依赖注入的方法,但是如果有的话,例如有一些配置变量需要用构造方法定义的话,这种就没法起作用了。
所以这种情况下我们就需要用服务容器的方法了,我们打开App/Providers/AppServiceProvider.php这个文件,我们会看到两个方法:register和boot.
我们可以在注册这个方法里用bind这个方法来绑定变量,例如:
public function register(){
$this->app->bind(PaymentGateway::class, function($app){
return new PaymentGateway('currency');
//返回一个新实例,并且绑定currency这个变量
})
}
当然这回我们可以直接在这里把变量导入进去。
这样我们就可以在别的控制器里以依赖注入的方式导入这个类而不用更改其他文件,只需要更改这个类便可。
所以当你用bind方法的时候,每一次调用这个PaymentGateway的时候,一个新的实例会返回。
当然这里我们常用的是singleton这个方法,当我们用到PaymentGateway的时候,Laravel会在容器里寻找这个PaymentGateway对象,我们返回的是同一个对象。
public function register()
{
$this->app->singleton(PaymentGateway::class, function($app){
return new PaymentGateway('usd');
})
}
如果我们假设新加了两个支付方式,例如CreditCardPaymentGateway.php和BankPaymentGateway这两个,但是很多方法都是跟PaymentGateway是一样的。我们该如何做呢?
我们可以创建一个接口,把相同的方法做成一个接口,用两个类来落实这个接口。
例如:
class CreditCardPaymentGateway Implements PaymentGatewayContract {
}
这里的PaymentGatewayContract是个接口。同样的,我们可以让BankPaymentGateway也是实施这个接口。
这样我们可以把这个singleton方法改成:
$this->app->singleton(PaymentGateway::class, function($app){
return new PaymentGateway('usd');
这样我们可以判断用户的行为来判断返回的是什么对象:
$this->app->singleton(PaymentGatewayContract::class, function($app){
if(request()->has('credit')){
return new CreditCardPaymentGateway('usd');
}
//判断get变量credit是否是true
return new BankPaymentGateway();
});
网友评论