服務(wù)容器是Laravel必要了解的一個(gè)概念。服務(wù)容器是告訴Laravel如何構(gòu)造一個(gè)class或者對(duì)象馆衔,使得Laravel可以從此配置你的class或者對(duì)象。官網(wǎng)上說服務(wù)容器是一個(gè)非常強(qiáng)大的管理類依賴和依賴注入的工具怨绣。其實(shí)我們看下例子可以更容易地理解它角溃。
我們知道Laravel可以利用添加namespace的方式引入外部類文件。但是如果我們創(chuàng)建了一個(gè)控制器梨熙,我們引入的時(shí)候可能需要實(shí)例化一下开镣。
但是如果是在laravel內(nèi)部了刀诬,那么我們可以直接以依賴注入的方式注入到控制器的某個(gè)方法里咽扇。例如:
namespace App\Http\Controllers;
use App\Handlers\PaymentGateway;
class PayOrderController extends Controller {
public function store(PaymentGateway $paymentgateway){
}
}
我們?cè)O(shè)想一下如果PaymentGateway這個(gè)類沒有構(gòu)造方法和需要傳入一些變量的話,我們可以直接直接用依賴注入的方法陕壹,但是如果有的話质欲,例如有一些配置變量需要用構(gòu)造方法定義的話,這種就沒法起作用了糠馆。
所以這種情況下我們就需要用服務(wù)容器的方法了嘶伟,我們打開App/Providers/AppServiceProvider.php這個(gè)文件,我們會(huì)看到兩個(gè)方法:register和boot.
我們可以在注冊(cè)這個(gè)方法里用bind這個(gè)方法來綁定變量又碌,例如:
public function register(){
$this->app->bind(PaymentGateway::class, function($app){
return new PaymentGateway('currency');
//返回一個(gè)新實(shí)例九昧,并且綁定currency這個(gè)變量
})
}
當(dāng)然這回我們可以直接在這里把變量導(dǎo)入進(jìn)去绊袋。
這樣我們就可以在別的控制器里以依賴注入的方式導(dǎo)入這個(gè)類而不用更改其他文件,只需要更改這個(gè)類便可铸鹰。
所以當(dāng)你用bind方法的時(shí)候癌别,每一次調(diào)用這個(gè)PaymentGateway的時(shí)候,一個(gè)新的實(shí)例會(huì)返回蹋笼。
當(dāng)然這里我們常用的是singleton這個(gè)方法展姐,當(dāng)我們用到PaymentGateway的時(shí)候,Laravel會(huì)在容器里尋找這個(gè)PaymentGateway對(duì)象剖毯,我們返回的是同一個(gè)對(duì)象圾笨。
public function register()
{
$this->app->singleton(PaymentGateway::class, function($app){
return new PaymentGateway('usd');
})
}
如果我們假設(shè)新加了兩個(gè)支付方式,例如CreditCardPaymentGateway.php和BankPaymentGateway這兩個(gè)逊谋,但是很多方法都是跟PaymentGateway是一樣的擂达。我們?cè)撊绾巫瞿兀?/p>
我們可以創(chuàng)建一個(gè)接口,把相同的方法做成一個(gè)接口胶滋,用兩個(gè)類來落實(shí)這個(gè)接口谍婉。
例如:
class CreditCardPaymentGateway Implements PaymentGatewayContract {
}
這里的PaymentGatewayContract是個(gè)接口。同樣的镀钓,我們可以讓BankPaymentGateway也是實(shí)施這個(gè)接口穗熬。
這樣我們可以把這個(gè)singleton方法改成:
$this->app->singleton(PaymentGateway::class, function($app){
return new PaymentGateway('usd');
這樣我們可以判斷用戶的行為來判斷返回的是什么對(duì)象:
$this->app->singleton(PaymentGatewayContract::class, function($app){
if(request()->has('credit')){
return new CreditCardPaymentGateway('usd');
}
//判斷get變量credit是否是true
return new BankPaymentGateway();
});