作為一個新手,看laravel官方文件時,總會想去看看原始碼是怎麼實現的。
在看到表單驗證那一塊時,很好奇Request類呼叫validate方法與Validator::make()有什麼區別?
Validator::make()倒是一下子看懂了,其實這只是呼叫了個外觀類,但$request->validate()就有點看不懂了……
先去Request檔案看看
發現只寫了幾個註釋
@method array validate(array $rules, …$params)
並沒有相應的方法,去它的父類裡看發現也沒有
魔法方法__call()
這種時候就想到了__call() 可以呼叫非本類中的方法,一找發現還是沒有。
很納悶,用反射類獲取Request類的所有方法getMethods(),發現是有__call()的。
有點懵逼,遂發現Request用了幾個Traits,主意檢視,發現其中的Macroable是有__call()的
Macroable的__call()
那麼$request呼叫validate()一定是通過這個__call()的。看看裡面寫了啥。
發現這個方法非常簡單,就是看靜態陣列$macros中是否包含相應方法,有就呼叫。
那麼問題來了,$macros陣列中的方法是哪裡來的 laravel真的好繞
FoundationServiceProvider
Kernel在進行handle()處理請求時,會先進行bootstrap階段,這時會載入config/app中的provider,FoundationServiceProvider就是其中一個。它在register()階段,執行了registerRequestValidation()方法。
registerRequestValidation()
給靜態陣列$macros註冊validate、validateWithBag方法
原始碼:
// validator() 是在helper.php中
生成一個ValidationFactory(Illuminate\Contracts\Validation\Factory)的例項,並將該例項的validate方法註冊到$macros陣列中。
但是注意,這個Illuminate\Contracts\Validation\Factory是一個介面類,一定在什麼地方已經和一個具體類進行了繫結~
注意: 一般框架自帶的工具類,都會將簡稱和相應類名放在別名陣列中。知道是為什麼嗎?
在Illuminate\Foundation\Application的建構函式中,有一個registerCoreContainerAliases()方法,它裡面將一些簡稱和相應的類名關聯起來,放到aliases陣列和abstractAliases陣列中
做這些aliases陣列和abstractAliases陣列的目的呢,我之前沒想明白,現在明白了 就是在遇到像上面要例項化Illuminate\Contracts\Validation\Factory介面類時,自動做轉換,轉換為validator(而validator的繫結會在相應的provider中做掉)
結論
再來看看手動生成驗證器
Validator::make()呢其實就是通過Facade來操作例項
巧了,也是validator!說明手動生成驗證器和使用$request->validate() 其實呼叫的方法是一樣的。
Validator這種外觀類是怎麼實現的,我這裡就不說了,社群裡一篇帖子分享一下
部落格:深入淺出 Laravel 的 Facade 外觀系統
最後找找validator繫結的具體類
在config/app的providers中查詢,發現是在Illuminate\Validation\ValidationServiceProvider中register()時繫結了validator
繫結的類是Illuminate\Validation\Factory
一開始看laravel原始碼真的很痛苦,不過看多了會發現套路都差不多,努力學習!
本作品採用《CC 協議》,轉載必須註明作者和本文連結