第一次看到這個檔案的時候,看到這麼多的方法卻找不到出處,心裡很是著急。只能到處找答案了。
現在來解釋說明一下
這個方法會執行,新增別名對映。
上面那些註釋方法,一個是 db 對應類的,一個是 db.connection 對應類的。
Facade 是門面的意思,這個 DB 繼承它,表示一個門面
- $app->get(\Illuminate\Support\Facades\DB::class)
- => $app->get(\Illuminate\Support\Facades\DB::getFacadeAccessor())
- => $app->get(‘db’)
- => $app->get(\Illuminate\Database\DatabaseManager::class)
容器獲取物件,先透過門面類,獲取門面類返回的接受訪問物件(是一個字串標識),再去訪問這個標識,找到標識繫結的類,上面程式碼表面獲取的是表面上獲取的是 \Illuminate\Support\Facades\DB::class 物件,實際上獲取的是 \Illuminate\Database\DatabaseManager::class 物件
為什麼這麼設計呢?
$app[‘DB’] => $app->DB => $app->get(‘DB’) 三個是一樣的
這些入口識別符號都是極具語義化的,明確表達了功能模組的型別,$app[‘語義化入口識別符號’] 這樣的容器獲取功能模組的方法十分清晰。
為什麼中間加入門面別名,而不是直接對映到具體的類?
因為每種功能模組,可能細化為多種型別,一個門面代表一種型別;透過修改配置檔案的別名(更改門面),達到功能模組具體執行的型別。
比如你要個水果,有兩個門面,一個蘋果,一個梨子,改下水果對應的門面型別,就行了,買蘋果,就去蘋果店;買梨子,就去梨子店。
門面就是一個選擇/決策;但是它有具體東西,比如這個 Illuminate\Support\Facades\DB 門面,返回了 db 那麼這個門面的實體就是 db。但是,db 不是最底層的,db 還對映到了 Illuminate\Database\DatabaseManager
就是說,laravel container(容器)的別名對映關係可能是多層次的,識別符號 => 實體類,
中間可能經過多次別名傳遞,因為支援別名還有別名,所以配置別名的時候,不能亂搞,亂配置弄出死迴圈。你配置了什麼別名,你要心裡有數為什麼說 變數、類名、函式名、類名、方法名 等等都要 語義化
最簡單的容器,就是根據類名建立物件
更進一步,新增 介面=>類 對映,然後透過 介面/類名 建立物件
再更近一步,新增 識別符號 => 類,透過識別符號建立物件
再更進一步,多層對映關係,透過 識別符號 找到最基礎的類的物件
再更進一步,萬物接物件,透過識別符號可以獲取任何型別資料
原本是對映到實體型別,現在可以繫結閉包,透過識別符號獲取這個閉包的執行結果,容器透過識別符號獲取物件,就是處理 識別符號 的多層別名關係,得到實體型別或閉包,然後建立類或返回閉包執行結果。有單例,就有非單例,有些實體的獲取,需要提供引數,然後又加了個 make(string $id, array $parameters = []) 方法。
理論上,容器應該只獲取單例。需要明顯區分的引數,就沒必要讓容器來建立,你直接獲取引數,自己建立得了。但是,容器設計者都比較貪心,容器的最大功能就是處理引數的依賴關係,單例非單例都讓它做得了。
開始是個小容器,後面越寫功能越複雜,你懂得,讓作者自己看原始碼,都會頭痛,時間久了,要是忘記自己設計時的一些“約定”,自己看著都費勁。
本作品採用《CC 協議》,轉載必須註明作者和本文連結