## MVC架構
> **控制器** > **邏輯層/服務層** > **模型層**
**控制器:** 承接前端請求,好的設計應該是“瘦”控制器。也可以被其它控制器調用。
**邏輯層:** 業務邏輯代碼主要在邏輯層,“胖”邏輯層。可以被控制器直接調用,也可被其他邏輯層或服務層調用。(業務邏輯就是跟業務相關的邏輯,其中很重要的就是sql操作,這些sql是具有意義的,業務最終會落地到sql上去體現,其意義就是表現業務邏輯——或者說sql其實就是邏輯sql。)
**服務層:** 和邏輯層類似,可以被控制器直接調用,也可被邏輯層或其他服務層調用。
**模型層:** 數據操作層,被服務層或邏輯層調用,甚至簡單的被控制器直接調用(不推薦)。定義數據結構,驗證規則。提供DB操作方法。任何一張數據表都是一個模型(每張表的每個字段決定了數據的格式,規則),邏輯層需要保存更改數據時調用各個模型完成ORM操作持久化到數據庫。
>[danger] 關鍵的地方就在于模型層和Db層的結合,數據模型層在操作時自己會連接數據庫執行sql(惰性連接數據庫),也會自己斷開連接,模型層無需關系Db層的情況,對模型層完全屏蔽了Db層的復雜性,操作模型層感覺不到sql。
(Db層其實就沒有了,被抽象到模型中去了(模型也是利用Db類執行sql),模型隱藏了Db、sql操作的細節,當然Db也是可以單獨靈活調用的,此時Db就相當于一個Db操作工具庫了,有點類似于前端中的jQuery的身份了,不過還是建議都定義模型類來進行抽象操作。不過在快速開發初期為了方便也是可以直接Db類的,方便,不過要知道這樣做并不是一個好習慣。)
> 任何一個方法,不論什么層,只需要關注,它接收什么參數,內部做什么操作,返回什么數據。我們的所有代碼幾乎都是在做這樣的事情。
**補充:**
模型層不要有任何的業務邏輯,模型層只提供數據的定義,和Db(實際上模型層和Db層是緊密相連的,模型層對外屏蔽了Db層的),模型層被邏輯層調用,模型層只能被調用,不能調用別人,一個業務邏輯可能包含多個模型,多條sql,所以模型層必須單純,只提供數據定義就可以了,剩下的交給邏輯層。控制器起一個調度作用,理論上控制器一上來全部調用邏輯層,甚至每個控制器都有一一對應的邏輯層都可以,但是對于比較簡單的請求,也可以不需要邏輯層,但是控制器中一定不要出現業務邏輯,特別是有sql的,控制器只能調用邏輯層和服務層,千萬不要自己調用模型層來做事,所以控制器其實每個方法的代碼量很少,大部分代碼都在邏輯層和服務層,**業務邏輯主要就是sql操作**,切記sql只能出現在邏輯層和服務層中,大家各司其職,都保持單純點,對外提供單一功能,這樣系統就會更加可靠,便于維護。
以前的系統,很多業務邏輯都在模型層,比如給模型層定義各種各樣的方法,模型層既有業務邏輯,又承擔數據的定義和提供Db,這樣太雜了,不利于維護。
**模型層用起來感覺像是使用Db一樣。所以如非必要就不要去直接使用Db類。**
> 模塊是數據和方法的集合。
* * * * *
### 擴展
[為什么我們要用函數式編程](https://www.toutiao.com/a6435902552059478273/?tt_from=weixin&utm_campaign=client_share×tamp=1515522953&app=news_article&utm_source=weixin&iid=22069500288&utm_medium=toutiao_android&wxshare_count=1)
> **簡單來說,也就是當一個函數的輸出不受外部環境影響,同時也不影響外部環境時,該函數就是純函數。**(面向對象就不同了,方法的輸出結果與運行環境的上下文有關。)
[面向對象圣經](http://mp.weixin.qq.com/s/DZyn2w6ci86qt73gIJjzqA)
[函數式編程圣經](http://mp.weixin.qq.com/s/0gErQ3tjDLZuD1bYOhi0mQ)
[左耳朵耗子:什么是函數式編程?](https://mp.weixin.qq.com/s/nh5qifdneF_Y3xOJBy_ipg)
> “所以代碼在并行上根本不需要鎖”:因為沒有競態資源。
[PHP 后端組織項目結構的思考](http://mp.weixin.qq.com/s?__biz=MjM5NTEwMTAwNg==&mid=2650211377&idx=2&sn=259beb5e5c59be2c059b506f290dd62a&chksm=befe041089898d0648c6a8123d24cc1d40d40c29fa0bc6da901eed49393123cacfdb24e29a33&scene=21#wechat_redirect)
[PHP設計模式系列:目錄 - CSDN博客](http://blog.csdn.net/qq_32300363/article/details/71078666)
[【譯】深入研究 Laravel 的依賴注入容器](https://mp.weixin.qq.com/s/yFjmrXAe9S45JqBAUgobhA)
[你真的理解了MVC, MVP, MVVM嗎?](http://mp.weixin.qq.com/s/EzxfJLb5Hjxyw0_S5rThvg)
[教你在不使用框架的情況下也能寫出現代化 PHP 代碼](https://mp.weixin.qq.com/s/iQSmVPRwiqTADm1Ol4a6Eg)
[隔離 View 和 Model (Swift)](https://mp.weixin.qq.com/s/Mi3B8ysGCBT9LfYeo8HGKw)
[10 個常用的軟件架構模式](https://mp.weixin.qq.com/s/PjHEpKqoMX-NdJF102xklw)
[為什么要用單例模式?](https://mp.weixin.qq.com/s/rQQTonFsesSk2E1Vtymh9Q)
[Web 框架的架構模式探討](https://mp.weixin.qq.com/s/EAEDYl9a9MRFDeHj4RgPRA)
> 想象一下沒有 MVC 架構模式,可能所有的 Web 框架必然的會實現一套幾乎解決同樣問題的方案,但是命名和文檔卻各不一樣,當你去看一個新的框架文檔的api 接口,從頭到尾看完以后才恍然大悟,這不就是之前用的框架里面的 XXX 類似嗎,這樣的編程世界簡直地獄。慶幸的是,得益于計算機科學家(碼農)對問題和方案持續的抽象成模式,使得當前高度復雜的計算機科學也能得到合理分層和適配,大大簡化了學習和溝通的成本。
[聊聊設計模式之工廠方法模式](https://mp.weixin.qq.com/s/UaVd9iGkOVR4JgYFhDxrQg)
[maven最佳實踐之模塊劃分](https://mp.weixin.qq.com/s/ZMKrfwNilsJUre13eygtvg)
[為什么說 Java 程序員到了必須掌握 Spring Boot 的時候?](https://mp.weixin.qq.com/s/jwgsJnj0V21xAJnBsj_VvA)
> 在此引用 Python 的經典設計格言,格言來源于 Python 但不限于 Python。
>
> 美麗優于丑陋。
> 清楚優于含糊。
> **簡單優于復雜。**
> 復雜優于繁瑣。
> 平坦優于曲折。
> 寬松優于密集。
> 重要的是可讀性。
> **特殊的案例不足以特殊到破壞規則。**
> **盡管實踐可以打破真理。**
> **錯誤卻不可置之不理。**
> **除非另有明確要求。**
> **面對模棱兩可,拒絕猜測。**
> **總會有一個 —— 最好是只有一個 —— 顯而易見的方式來明辨。**
> 哪怕這種方式在開始的時候可能并不明顯。
> 現在有比沒有好。
> 盡管沒有經常好于現在。
> 如果如何實現很難被解釋清楚,那么這個想法就是一個壞想法。
> 如果如何實現可以被很好的解釋,那么這是一個好想法。
[責任鏈模式實現的三種方式](https://mp.weixin.qq.com/s/ZuOsksqLKCWBnALmO6ZkDg)
> 責任鏈模式不就違背了不能相互耦合的規則。相反責任鏈是為了解決耦合問題。
[PHP程序員如何理解IoC/DI - zhaoyi - SegmentFault 思否](https://segmentfault.com/a/1190000002411255)
[PHP程序員如何理解依賴注入容器(dependency injection container) - zhaoyi - SegmentFault 思否](https://segmentfault.com/a/1190000002424023)
[PHP中的服務容器與依賴注入的思想 - 逸夢 - SegmentFault 思否](https://segmentfault.com/a/1190000015449325)
[PHP容器--Pimple運行流程淺析 - 飛鴻影~ - 博客園](https://www.cnblogs.com/52fhy/p/7102083.html)
[Pimple - 一個簡單的 PHP 依賴注入容器 - 小碼農的打怪 - SegmentFault 思否](https://segmentfault.com/a/1190000014471794)
[使用 Laravel 服務容器的優勢 - 個人文章 - SegmentFault 思否](https://segmentfault.com/a/1190000015463623)
使用了了laravel服務容器以后:
```php
/**
*發送郵件服務類
*/
class EmailService{
public function send(){
//todo 發送郵件方法
}
}
$this->app->bind('emailService', function ($app) {
// 這兒就是中間層,也就是實現解耦的地方了,后期可以靈活變動,而無需更新硬編碼的部分
return new EmailService();
});
//如果任何地方要發郵件我們就復制下面這兩行代碼
// 調用部分,這兒就是硬編碼了
$emailService = app('emailService');
$emailService->send();
```
還記得計算機的一切問題都可以通過封裝來解決嗎?
上面的模型其實最簡單的三層模型:
服務(能力提供) > 中間層(解耦) > 調用處(執行動作)
* * * * *
last update:2018-2-14 18:15:31
- 開始
- 公益
- 更好的使用看云
- 推薦書單
- 優秀資源整理
- 技術文章寫作規范
- SublimeText - 編碼利器
- PSR-0/PSR-4命名標準
- php的多進程實驗分析
- 高級PHP
- 進程
- 信號
- 事件
- IO模型
- 同步、異步
- socket
- Swoole
- PHP擴展
- Composer
- easyswoole
- php多線程
- 守護程序
- 文件鎖
- s-socket
- aphp
- 隊列&并發
- 隊列
- 講個故事
- 如何最大效率的問題
- 訪問式的web服務(一)
- 訪問式的web服務(二)
- 請求
- 瀏覽器訪問阻塞問題
- Swoole
- 你必須理解的計算機核心概念 - 碼農翻身
- CPU阿甘 - 碼農翻身
- 異步通知,那我要怎么通知你啊?
- 實時操作系統
- 深入實時 Linux
- Redis 實現隊列
- redis與隊列
- 定時-時鐘-阻塞
- 計算機的生命
- 多進程/多線程
- 進程通信
- 拜占庭將軍問題深入探討
- JAVA CAS原理深度分析
- 隊列的思考
- 走進并發的世界
- 鎖
- 事務筆記
- 并發問題帶來的后果
- 為什么說樂觀鎖是安全的
- 內存鎖與內存事務 - 劉小兵2014
- 加鎖還是不加鎖,這是一個問題 - 碼農翻身
- 編程世界的那把鎖 - 碼農翻身
- 如何保證萬無一失
- 傳統事務與柔性事務
- 大白話搞懂什么是同步/異步/阻塞/非阻塞
- redis實現鎖
- 淺談mysql事務
- PHP異常
- php錯誤
- 文件加載
- 路由與偽靜態
- URL模式之分析
- 字符串處理
- 正則表達式
- 數組合并與+
- 文件上傳
- 常用驗證與過濾
- 記錄
- 趣圖
- foreach需要注意的問題
- Discuz!筆記
- 程序設計思維
- 抽象與具體
- 配置
- 關于如何學習的思考
- 編程思維
- 談編程
- 如何安全的修改對象
- 臨時
- 臨時筆記
- 透過問題看本質
- 程序后門
- 邊界檢查
- session
- 安全
- 王垠
- 第三方數據接口
- 驗證碼問題
- 還是少不了虛擬機
- 程序員如何談戀愛
- 程序員為什么要一直改BUG,為什么不能一次性把代碼寫好?
- 碎碎念
- 算法
- 實用代碼
- 相對私密與絕對私密
- 學習目標
- 隨記
- 編程小知識
- foo
- 落盤
- URL編碼的思考
- 字符編碼
- Elasticsearch
- TCP-IP協議
- 碎碎念2
- Grafana
- EFK、ELK
- RPC
- 依賴注入
- 開發筆記
- 經緯度格式轉換
- php時區問題
- 解決本地開發時調用遠程AIP跨域問題
- 后期靜態綁定
- 談tp的跳轉提示頁面
- 無限分類問題
- 生成微縮圖
- MVC名詞
- MVC架構
- 也許模塊不是唯一的答案
- 哈希算法
- 開發后臺
- 軟件設計架構
- mysql表字段設計
- 上傳表如何設計
- 二開心得
- awesomes-tables
- 安全的代碼部署
- 微信開發筆記
- 賬戶授權相關
- 小程序獲取是否關注其公眾號
- 支付相關
- 提交訂單
- 微信支付筆記
- 支付接口筆記
- 支付中心開發
- 下單與支付
- 支付流程設計
- 訂單與支付設計
- 敏感操作驗證
- 排序設計
- 代碼的運行環境
- 搜索關鍵字的顯示處理
- 接口異步更新ip信息
- 圖片處理
- 項目搭建
- 閱讀文檔的新方式
- mysql_insert_id并發問題思考
- 行鎖注意事項
- 細節注意
- 如何處理用戶的輸入
- 不可見的字符
- 抽獎
- 時間處理
- 應用開發實戰
- python 學習記錄
- Scrapy 教程
- Playwright 教程
- stealth.min.js
- Selenium 教程
- requests 教程
- pyautogui 教程
- Flask 教程
- PyInstaller 教程
- 蜘蛛
- python 文檔相似度驗證
- thinkphp5.0數據庫與模型的研究
- workerman進程管理
- workerman網絡分析
- java學習記錄
- docker
- 筆記
- kubernetes
- Kubernetes
- PaddlePaddle
- composer
- oneinstack
- 人工智能 AI
- 京東
- pc_detailpage_wareBusiness
- doc
- 電商網站設計
- iwebshop
- 商品規格分析
- 商品屬性分析
- tpshop
- 商品規格分析
- 商品屬性分析
- 電商表設計
- 設計記錄
- 優惠券
- 生成唯一訂單號
- 購物車技術
- 分類與類型
- 微信登錄與綁定
- 京東到家庫存系統架構設計
- crmeb
- 命名規范
- Nginx https配置
- 關于人工智能
- 從人的思考方式到二叉樹
- 架構
- 今日有感
- 文章保存
- 安全背后: 瀏覽器是如何校驗證書的
- 避不開的分布式事務
- devops自動化運維、部署、測試的最后一公里 —— ApiFox 云時代的接口管理工具
- 找到自己今生要做的事
- 自動化生活
- 開源與漿果
- Apifox: API 接口自動化測試指南