## 框架分層規范
PHP行業常見框架分層為基礎MVC,但是對于企業級應用且研發團隊超過10人以上時并不適用
為了規范分層概念及研發標準特此在此文檔進行分層規范詳細定義
**此類規范并無絕對標準,重在統一規范,分層過多會帶來一定維護成本和代碼,各個開發團隊根據業務形態自行調整,如不確定可找我們進行討論分析。**
### 層級隔離性建議
* 同層代碼切勿相互引用調用,如出現此情況,建議將相互引用模塊中某個模塊降級到下一層,此舉可提高業務代碼隔離性
* 上層服務可調用下層服務,不可下層服務反向調用上層服務,簡化降低業務代碼復雜度
通過以上設計,可以大量減少引用層級,方便未來業務管理拆分,代碼縱向切面清晰完整。
### 關于最大分層
最大分層是指當業務復雜到一定程度,極限情況下的分層設計。
如業務簡單則可對如下分層進行合并無需完全實現,具體可根據業務情況自行劃分。
#### 具體分層如下:
* **Controller**
* **ServiceHelper**
* **Service**
* **Module**
* **Model**
分層的好處在于每一層完全隔離下一層所有細節接口規范統一,方便調用,對外提供服務規范文檔,對內提供服務方便簡單。
下面將會對具體分層功能職責、功能、規范進行詳細介紹
**注意:特殊情況特殊分析,歡迎找我們進行討論進一步分析。**
* * *
## Controller
* 對外業務封裝層,所有對外接口頁面封裝必須都在此層,其他層級代碼外部請求皆不可訪問
* 本層支持多級目錄,默認請求路徑與controller目錄層級一致,如/user/login默認請求路徑為www.xxx.com/user/login
* 外部請求常見在url中包含參數,本框架也支持此方式但此舉不推薦,主要原因對未來數據監控整理會帶來大量工作
* Controller層代碼禁止調用Controller層代碼,限制過度引用可大量降低后續維護成本,如有此類業務需求,請將被調用代碼降級到下一層內引用。
* 禁止在此層直接調用Service層及以下模塊,如model、module、ORM配置層
* 本層只調用Service進行業務拼裝,調用Service不建議直接new Service類,請使用 app() 封裝對Service進行調用
* 所有用戶請求參數必須做安全過濾驗證,后續會對輸入輸出數據用Request及Response進行統一封裝
## Service
* Service 服務層內是具體業務邏輯,可使用Moduel及Model對業務進行組裝,對輸入驗證,輸出格式都有統一的類進行封裝管理
* 本層支持多級目錄,具體可根據業務需要進行多層級封裝,不推薦超過兩層。如\\v1(版本,可選)\\user(類)\\login(函數)
* Service接口文檔后續會提供自動生成功能,但需要使用統一輸入驗證類方可(注意:此功能還在制作中)
* 建議封裝成可靈活組裝業務邏輯的粒度供Controller層組合,若牽扯事物建議最好在一個Service封裝完成
* Service層后續升級必須考慮兼容性,除非十分確認使用方會跟隨升級
* 底層及本層所有邏輯異常或底層異常會拋出Exception,此類Exception皆由ServiceHelper進行攔截,非必要、不要攔截
* 異常分兩種:業務異常請使用正整數(用戶未登錄),底層異常及框架異常請使用負數(Mysql connect error,redis went away)作為錯誤碼,通過這個簡單定義可以讓客戶端研發人員更好區分錯誤類型。
* 可復用性建議,同一個模塊或服務數據實體僅存一份文件不要出現同一個數據實體分布在多個目錄內情況,如User用戶相關操作最終對外提供Service服務時必須所有定義在一個Service主體內,如:用戶登陸有同樣三種封裝在不同文件內。 具體可以參考OOP設計思想進行設計,下面的module、modle也建議如此設計
* 同層Service代碼不允許調用或引用同層Service,如果出現建議將一些邏輯降級到Moduel或model層內。
* 請保證每一個Service都是無狀態的服務,不存在私有變量、static變量(factory變量除外)
## Module
* Module層是一個可選的分層,如果底層數據結構不是十分復雜可以忽略此層
* 若底層數據來源存在多種,可以使用此層將復雜的多來源的數據進行聚合**例如:**數據源來自Redis、Mysql以及第三方API協作,這樣可以匯總多來源Model
* 完全隔離底層數據來源及特征,對外提供標準的業務封裝及數據操作功能,對業務研發人員只需簡單調用即可使用
* 出現錯誤會拋出異常由業務組合層決定是否重試或提示用戶,也可以底層自帶多次重試,最后仍舊失敗后拋出異常
* 此層只能調用Model及ORM層配置定義且同上面幾層一樣,同層禁止相互調用,但是可以如下方式組合使用/module/user.php調用 /module/user/login.php使用,但不可反向,但是Service層盡量調用/module/user.php而/module/user/login.php屬于私有文件不上層提供任何服務。
* 如上其他層:一個數據實體對象只能存在一份定義和出入口
* 關于Cache,若數據來源復雜,可在此層對匯總后數據進行Cache
代碼示范:
## Model
* Model層有很多種數據來源,目前已知Redis,Mysql,其他服務提供的API,如果有多種來源有兩種組織方式。 根據數據來源分目錄后再根據對象名稱分子目錄或文件如/model/redis/user/user.php,不同來源不同目錄 根據model層內代碼匯總所有操作如/model/user/user.php(內含,api,redis,mysql所有操作)
* Model層對所有數據具體操作進行隔離,對外提供簡單調用即可實現對數據的增刪改查操作,此類封裝只做基礎封裝不做具體業務封裝,并不能保證業務事務完整性,如有此類聯動多數據源操作一應封裝在Module或Service層。
* 其中外層應保證傳遞數據做一些基礎的安全過濾,Model為了效率沒有對傳遞參數有效性做過多驗證檢測
* Fend底層也會做一定安全過濾,但由于一些限制能做的范圍有限。
* Model異常常見有兩種,操作失敗(Redis,Mysql,API請求失敗,斷開連接,事務失敗),傳遞參數錯誤,此類都會拋出Exception
* 關于Cache,Model層的Cache只能保存常見的單條數據以及一些不太復雜的查詢結果,如果對數據實時性較高不建議進行Cache,如來源是第三方提供的數據源(Mysql,Redis,API)是無法保證實時同步更新Cache的,此類情況可另外做訂閱更新,此類問題已經超出框架范疇。
## ORM
* 一般來說此層是隱含的,極少出現涉及本層單獨定義情況,如果業務使用大量Redis key且需要統一定義管理才會使用本層。