一、MVC模式
MVC模式(Model-View-Controller)是軟件工程中的一種軟件架構模式。
控制器(Controller)。負責轉發請求,對請求進行處理。
視圖(View)。界面設計人員進行圖形界面的設計。
模型(Model)。程序員編寫程序應有的功能(實現算法等),數據庫專家進行數據管理和數據庫設計(可以實現具體的功能)。即,數據和改變數據的操作。
可參考:https://laravelacademy.org/post/9614.html
二、框架結構
單一入口使得每一個請求都需經過這個入口文件處理,文件由此開始進行分發,減少重復存在一些通用的初始化操作,更容易管理Controller層。
路由:
路由是對來自客戶端的請求的URL解析,並把指定的URL分派給對應的 Controller 來處理。
一個Controller控制器又是由一組具有相關功能的Action組成,Action方法是一個URL訪問的最小單元。
路由就是找到這個控制器文件,並且執行它下面的方法。
數據模型:
1、數據庫類的實現
2、數據模型層理論
對象關系映射(Object Relational Mapping,簡稱ORM、O/RM 或 O/R mapping)。
把數據庫中的一個表直接映射為一個對象,基於這個對象進行賦值、保存等操作,並且減少寫SQL語句,提高開發效率。
PO(persistant object): 與一個數據庫中的表的一行記錄相對應的對象,稱之為PO持久對象。PO中應該不包含任何對數據庫的操作(也就是只有屬性,沒有方法),它僅僅是對表記錄的映射。
BO(business Object): 主要作用是把業務邏輯封裝為一個對象。這個對象可以包括一個或者多個其他對象。比如出貨單就包含有商品簡介、訂單詳情、消費者信息等。商品簡介對應一個PO,訂單詳情對應一個PO,消費者聯系信息對應一個PO。建立一個對應出貨單的BO對象處理出貨單,每個BO包含這些PO。這樣處理邏輯時,可以針對BO去處理。
VO(Value Object,值對象): 界面顯示的數據對象,一個界面對應一個VO對象。
DTO(Data Transfer Object): 傳輸PO對象到VO進行一些過濾。它可以用在任何需要數據傳輸的地方。
注意:在創建PO、DTO、VO時,不要給這些對象賦初始默認值。
傳統的ORM模式提倡數據和數據操作分離。而在Active Record中,模型層集成了ORM的功能,它們既代表實體,包含業務邏輯,又是數據對象,並負責把自己存儲到數據庫中,存儲的這一部分代碼是在父類中實現好的,屬於框架的一部分,模型只需要簡單調用父類的方法來完成持久化。在Active Record模式中的數據對象不再是PO對象,而是DAO(Data Access Object)對象。
比如,User類繼承了父類Model,擁有父類父類所擁有的增刪改查等功能(比如調用save()方法,實現數據保存;但其內部還是使用SQL拼裝實現數據庫操作,只是封裝好后使用ORM會自動生成SQL語句;一般用ORM實現簡單的CURD操作,復雜的查詢還是更傾向於使用原生的SQL實現),進而User這個PO對象上升為一個Dao對象。
Service:把一系列的數據庫操作組合起來,稱之為Service。向上負責接收頁面傳遞的參數以及數據的傳輸,向下負責與數據庫打交道。
視圖:
早期,使用smarty等專業的模板引擎來做視圖層,后期,隨着前后端分離理念的發展以及前端MVC框架的誕生,越來越多涉及顯示的工作都由前端JavaScript +JSON來實現了。MVC中的顯示層開始輕量化、API化發展。
三、框架加強
1、命名空間
詳見:https://www.php.net/manual/zh/language.namespaces.basics.php
2、自動加載
composer自動加載一共支持4種自動加載方式:
PSR-0:由於PHP5.3之后才有的namespace這樣的高級屬性,所以低於此版本的,PSR組織用了一個偽namespace(通過命名的下划線來映射目錄結構)的做法來模擬命名空間。
被結合為一個單一的鍵值對數組,存儲至 autoload_namespaces.php 文件中。
PSR-4(推薦):轉換成namespace與文件目錄的MAP形式,並存在 autoload_psr4.php 文件中,可以在此文件中找到真實路徑
class-map:支持自定義加載不遵循PSR-0/4規范的類庫。要配置它指向需要的目錄,以便能夠准確搜索到類文件。會遍歷此目錄然后將里面的類文件和路徑一一對應,存放在autoload_classmap.php 內。
直接包含file:可以直接將文件包含進來。安裝后會存放在 autoload_files.php 文件中。
詳見:
https://www.cnblogs.com/cshaptx4869/tag/Composer/
https://docs.phpcomposer.com/04-schema.html#autoload
3、錯誤處理機制
set_error_handler()
set_exception_handler()
詳見:https://www.cnblogs.com/cshaptx4869/p/10454086.html
4、控制反轉 IOC(inversion of control)與 依賴注入DI(dependency injection)
控制反轉是面向對象開發中的一種設計思想。IOC意味着將你設計好的對象交給容器控制,而不是直接在你的對象內部控制。
如何理解?明確“誰控制誰,控制什么,為何是反轉,哪些方面反轉了”。
誰控制誰,控制什么:傳統面向對象程序設計,我們直接在對象內部通過new進行創建對象,是程序主動去創建以來對象;而IOC是有專門一個容器來創建這些對象,即由IOC容器來控制對象的創建;所以,是IOC容器控制對象,主要控制了外部資源獲取(不只是對象創建,還包括比如文件等)。
為何是反轉,哪些方面反轉了:傳統下是自己在對象中主動控制去直接獲取依賴對象;反轉則是由容器來幫忙創建及注入依賴對象,由於容器幫我們查找及注入依賴對象,對象只是被動接受依賴對象,所以是反轉;總結一下就是,以前是由應用程序控制資源創建,現在控制權轉移到了IOC容器,所以叫控制反轉。
為什么這么做,這么做的意義何在?
依賴注入,是組件之間依賴關系由容器在運行期決定。即由容器動態地將某個依賴關系注入到組件之中。依賴注入的目的並非是為軟件系統帶來更多功能,而是為了調高組件重用的效率,並為系統搭建一個靈活、可擴展的平台。通過依賴注入機制,我們只要通過簡單的配置,而無需任何代碼就可指定目標需要的資源,完成自身的業務邏輯,而不需要關系具體的資源來自何處,由誰實現。依賴注入降低了創建對象的成本,使得對象之間松耦合。
DI的關鍵是“誰依賴誰,為什么需要依賴,誰注入誰,注入了什么”。
為什么需要依賴:應用程序需要IOC容器來提供對象需要的外部資源。
誰注入誰:IOC容器注入應用程序某個對象,應用程序依賴的對象。
注入了什么:注入某個對象所需要的外部資源(包括對象、資源、常量數據)。
DI和IOC是相輔相成的概念,IOC的實現是使用了DI,而DI的目的就是為了實現IOC。
依賴注入DI和控制反轉IOC是對同一件事情的不同描述,它們描述的角度不同。依賴注入是從應用程序的角度在描述,應用程序依賴容器創建並注入它所需要的外部資源。而控制反轉是從容器的角度在描述,容器控制應用程序,由容器反向的向應用程序注入應用程序所需要的外部資源。
IOC會使用最合適的策略來管理對象,需要使用單例的地方,容器就始終只提供一個對象。需要使用多例的時候,容器就每次幫我們創建一個新對象(當然也可以手動告訴容器怎么做)。
實際上IOC容器本身也就是個大對象,在整個生命周期里保證只有一份。可以保存在Session中,也可以保存在內存中。
詳見:https://github.com/kevinyan815/Learning_Laravel_Kernel/blob/master/articles/IocContainer.md
5、攔截器和插件
攔截器可以用來作為權限控制、處理輸入和輸出等場景。
所有的攔截器組成一個攔截棧,按照從上到下進入,然后從下到上退出的順序進行調用。
具體實現:可以定義一個攔截器接口InterceptorInterface,子類去實現,然后在配置中正則定義哪些請求需要使用(如定義數組)。
整個流程是,所有請求會按照配置中的攔截器棧,從上到下走一遍,激活攔截器前置preHandle方法,然后激活控制器自帶的_bofore_方法(如果有的話),再激活當前需要執行的Action,緊接着是控制器再帶的_after_方法(有的話),然后從上到下方向激活攔截器的postHandle方法。
實現插件也是同理,定義一組插件接口,然后用戶自己擴展這個接口。框架只需要啟動時自動讀取所有實現了Plugin接口的類,並初始化注入框架的上下文環境即可。
6、Request增強和安全防御
XSS、CSRF、SQL注入等過濾
避免跨站請求偽造攻擊的措施就是對寫入操作采用非 GET 方式請求,同時在請求數據中添加校驗 Token 字段,Laravel 也是這么做的