今天要來理解 Laravel 的「靈魂」之一:
Service Container(服務容器) 與 依賴注入(Dependency Injection, DI)
想像你在玩積木:
在 Laravel 中,Service Container 主要用來:
假設我們有一個 PaymentService
負責處理付款:
class PaymentService {
public function pay($amount) {
return "已付款 {$amount} 元";
}
}
如果沒有 Service Container,我們可能會在控制器裡這樣:
$payment = new PaymentService();
echo $payment->pay(100);
問題是,如果有很多地方都用到 PaymentService
,而且未來要換成 StripePaymentService
,就得全部手動改,很麻煩
在 AppServiceProvider
的 register()
方法中:
public function register()
{
$this->app->bind(PaymentService::class, function ($app) {
return new PaymentService();
});
}
在控制器:
use App\Services\PaymentService;
class OrderController extends Controller
{
public function checkout(PaymentService $payment)
{
return $payment->pay(200);
}
}
Laravel 會看到
PaymentService $payment
,自動去容器找並建立實例
依賴注入 = 物件不自己建立所依賴的類別,而是「外面幫它準備好再傳進去」
好處:
new
假設有兩個付款系統:
interface PaymentInterface {
public function pay($amount);
}
class PaypalPayment implements PaymentInterface {
public function pay($amount) {
return "用 PayPal 付款 {$amount} 元";
}
}
class StripePayment implements PaymentInterface {
public function pay($amount) {
return "用 Stripe 付款 {$amount} 元";
}
}
在 Service Provider 中綁定:
$this->app->bind(PaymentInterface::class, StripePayment::class);
控制器:
public function checkout(PaymentInterface $payment)
{
return $payment->pay(300);
}
只要修改 Service Provider 的綁定,就能瞬間換付款系統,控制器不需要改
Service Container = Laravel 管理物件與依賴的工具箱
依賴注入(DI) = 不自己建立依賴物件,而是外部傳入
好處: