Laravel 中的依賴注入和 IoC 實現

柳旦旦發表於2021-01-14

在 Laravel 中,有一個叫“服務容器的東西”,用於管理類的依賴和執行依賴注入的工具。
類的依賴項通過建構函式,或者通過 setter 方法注入到類中。

程式碼

<?php

namespace App\Http\Controllers;

use App\User;
use App\Repositories\UserRepository;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * 使用者儲存庫的實現。
     *
     * @var UserRepository
     */
    protected $users;

    /**
     * 建立新的控制器例項。
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }

    /**
     * 顯示指定使用者的 profile。
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id)
    {
        $user = $this->users->find($id);

        return view('user.profile', ['user' => $user]);
    }
}

分析

因為控制器 UserController 需要從資料來源中獲取 user 物件,所以通過構造器注入的方式注入了 user 的服務,UserRepository 可能是使用 ORM 從資料庫獲取了 user 資訊。

上邊這個例子是使用 建構函式的方式進行了依賴注入,當然,也可以使用 Setter 方法注入

class UserProvider{
    protected $connection;
    public function __construct(){
        ...
    }

    public function setConnection( Connection $con ){
        $this->connection = $con;
    }
    ...

還有 介面注入

interface ConnectionInjector{
    public function injectConnection( Connection $con );
}

class UserProvider implements ConnectionInjector{
    protected $connection;

    public function __construct(){
        ...
    }

    public function injectConnection( Connection $con ){
        $this->connection = $con;
    }
}

在 Laravel 中,先使用 bind() 函式進行服務繫結,使用 make() 函式進行解析,最後在容器內由 build() 函式建立並返回例項。

服務容器繫結

在 Larevl 中,幾乎所有的服務容器都是在 服務提供者(App\Providers) 中完成的

// 第一種繫結:簡單繫結
$this->app->bind('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app->make('HttpClient'));
});

// 第二種繫結:繫結一個單例
$this->app->singleton('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app->make('HttpClient'));
});

// 第三種繫結:繫結例項
$api = new HelpSpot\API(new HttpClient);
$this->app->instance('HelpSpot\API', $api);

// 第四種繫結:繫結原始值
$this->app->when('App\Http\Controllers\UserController')
    ->needs('$variableName')
    ->give($value);

在服務提供者中,通過 $this->app 變數來訪問容器,然後使用 bind 方法來註冊一個繫結,這個方法需要兩個引數,第一個引數是需要註冊的類名或者介面名稱,第二個引數則是返回類的例項的閉包。

參考文章:

xueyuanjun.com/post/9534

本作品採用《CC 協議》,轉載必須註明作者和本文連結
專注細節,慢慢提升自己。✍️

相關文章