主要:
常量?jī)?yōu)化路徑
自動(dòng)加載類(lèi)
優(yōu)化入口文件
安全訪問(wèn)項(xiàng)目目錄
----------------------------------------------------├─App│ ├─Model 模型│ │ └─UserModel.html' target='_blank'>class.php 用戶模型類(lèi) │ ├─View 視圖│ │ ├─Back后臺(tái)│ │ │ └─Index│ │ │ └─index.html 后臺(tái)首頁(yè)面│ │ └─Home前臺(tái)│ │ └─User 用戶視圖目錄│ │ └─login.html 登錄表單頁(yè)面│ ├─Controller 控制器│ │ ├─Back后臺(tái)│ │ │ └─IndexController.class.php 后臺(tái)首頁(yè)控制器│ │ └─Home前臺(tái)│ │ └─UserController.class.php 用戶控制器├─Public 靜態(tài)公共文件(js,css,images)│ ├─Plugins 插件│ │ └─layui 前端框架插件│ ├─Back后臺(tái)│ │ ├─js/ js文件│ │ ├─css/ css樣式文件│ │ └─image img圖片 │ └─Home前臺(tái)│ ├─js/ js文件│ ├─css/ css樣式文件│ └─image img圖片 ├─Frame 公共使用的類(lèi)│ ├─BaseModel.class.php 數(shù)據(jù)庫(kù)連接類(lèi)│ ├─BaseController.class.php 控制器公共操作(設(shè)置編碼,信息跳轉(zhuǎn))│ ├─FactoryModel.class.php 模型工廠類(lèi)│ ├─Init.class.php 初始化應(yīng)用類(lèi)│ └─MySQLDB.class.php 數(shù)據(jù)庫(kù)操作工具類(lèi)└─index.php 入口文件-----------------------------------------------------------------
上一篇中,提出4個(gè)問(wèn)題待解決,本篇集中解決這4個(gè)問(wèn)題,最終形成完整的微型MVC框架結(jié)構(gòu), 后續(xù)博客項(xiàng)目,或其他項(xiàng)目,均可以直接使用該框架結(jié)構(gòu)進(jìn)行開(kāi)發(fā)學(xué)習(xí)。
下載查看該項(xiàng)目源碼: https://gitee.com/NewbiesYang/young_blog
常量?jī)?yōu)化路徑準(zhǔn)備: 創(chuàng)建分支
1 $ git checkout master2 $ git checkout -b MVC思路
1)把常用的目錄路徑定義成常量。如 模型目錄,控制器目錄等
2)引入類(lèi)使用定義的常量替代部分路徑。 如 include FRAME.BaseModel.class.php
3) 載入視圖使用常量替代部分路徑 如 include VIEW. login.html 簡(jiǎn)單形式
1)操作步驟
step 1: 在入口文件中定義所需要的常量step 2: 控制器中引入視圖時(shí), 使用常量進(jìn)行優(yōu)化
操作步驟思路
2) 入口文件中定義常用路徑常量 【index.php】
1 ?php 2 /** 3 * 入口文件 4 */ 5 $p = !empty($_GET[ p ]) ? $_GET[ p ] : Home //平臺(tái) 6 $c = !empty($_GET[ c ]) ? $_GET[ c ] : User //控制器 7 $a = !empty($_GET[ a ]) ? $_GET[ a ] : login //動(dòng)作 9 define( PLAT , $p); //平臺(tái)常量 10 define( CTR , $c); //控制器 11 define( ACTION , $a); //動(dòng)作 14 define( DS , DIRECTORY_SEPARATOR); //目錄分割符 15 define( ROOT , getcwd().DS); //當(dāng)前所在目錄 項(xiàng)目目錄 16 define( FRAME , ROOT. Frame .DS); 17 define( APP , ROOT. App .DS); 18 define( PUB , ROOT. Public .DS); 19 define( ADMIN , PUB. Admin .DS); 20 define( HOME , PUB. Home .DS); 22 //MVC目錄 23 define( MODEL , APP. Model .DS); 24 define( VIEW , APP. View .DS.PLAT.DS.CTR.DS); 25 define( CTRONLLER , APP. Controller .DS.PLAT.DS); 27 $ctr = $c. Controller 29 require_once FRAME. Db.class.php //數(shù)據(jù)庫(kù)操作類(lèi) 30 require_once FRAME. BaseModel.class.php //基礎(chǔ)模型類(lèi) 31 require_once MODEL. UserModel.class.php //用戶模型類(lèi) 32 require_once FRAME. FactoryModel.class.php //模型工廠類(lèi) 33 require_once FRAME. BaseController.class.php //基礎(chǔ)控制器類(lèi) 34 require_once CTRONLLER.$ctr. .class.php 37 //實(shí)例化控制器 38 $userCtr = new $ctr(); 40 $userCtr - $a();
2) 常量的使用:
后臺(tái)首頁(yè)控制器【App/Controller/Admin/IndexController.class.php】
1 ?php 2 /** 3 * IndexController控制器類(lèi) 4 * 后臺(tái)相關(guān)操作 5 * User: young 6 */ 8 class IndexController extends BaseController 10 //展示后臺(tái)首頁(yè) 11 public function index() 12 { 13 include VIEW. index.html 14 } 15 }
后臺(tái)首頁(yè)控制器引入視圖路徑修改
用戶控制器 登錄視圖引入路徑【App/Controller/Home/UserController.class.php】
1 ?php 2 /** 3 * UserController.class.php 用戶控制器 4 */ 6 class UserController extends BaseController{ 7 /** 8 * 展示登錄界面 9 * @access public 10 */ 11 public function login() 12 { 13 include VIEW. login.html 14 } 15 。。。 16 。。。 17 。。。
用戶控制器登錄視圖引入路徑
3)提交代碼
$ git add -A$ git commit -m 常量使用自動(dòng)加載類(lèi) 思路
問(wèn)題: 入口文件中已經(jīng)require_once 引入6個(gè)類(lèi),既增加一個(gè)需要引入一個(gè),容易遺漏,重復(fù)和出錯(cuò)。
解決方法:自動(dòng)加載類(lèi)文件
方式1: 使用自動(dòng)加載類(lèi)函數(shù)__autoload()可以實(shí)現(xiàn)自動(dòng)加載
方式2: 實(shí)際項(xiàng)目中,多人開(kāi)發(fā),根據(jù)實(shí)用性,更多的是使用 sql_autoload_register()注冊(cè)函數(shù)自動(dòng)加載
根據(jù)目錄的特點(diǎn)實(shí)現(xiàn)自動(dòng)加載
Model類(lèi)文件特點(diǎn),以Model結(jié)尾的類(lèi)名 substr($className,-5)
Controller文件特點(diǎn): 以Controller結(jié)尾的類(lèi)名, substr($class,-10)
公共類(lèi): 類(lèi)名沒(méi)有統(tǒng)一形式,可以將Fame下的公共類(lèi)放入到數(shù)組中,然后判斷類(lèi)是否在數(shù)組中, 從而自動(dòng)加載該目錄下的類(lèi)文件
代碼實(shí)現(xiàn)1) 入口文件實(shí)現(xiàn)類(lèi)的自動(dòng)加載
1 ?php 2 /** 3 * 入口文件 4 */ 5 $p = !empty($_GET[ p ]) ? $_GET[ p ] : Home //平臺(tái) 6 $c = !empty($_GET[ c ]) ? $_GET[ c ] : User //控制器 7 $a = !empty($_GET[ a ]) ? $_GET[ a ] : login //動(dòng)作 9 define( PLAT , $p); //平臺(tái)常量 10 define( CTR , $c); //控制器 11 define( ACTION , $a); //動(dòng)作 14 define( DS , DIRECTORY_SEPARATOR); //目錄分割符 15 define( ROOT , getcwd().DS); //當(dāng)前所在目錄 項(xiàng)目目錄 16 define( FRAME , ROOT. Frame .DS); 17 define( APP , ROOT. App .DS); 18 define( PUB , ROOT. Public .DS); 19 define( ADMIN , PUB. Admin .DS); 20 define( HOME , PUB. Home .DS); 22 //MVC目錄 23 define( MODEL , APP. Model .DS); 24 define( VIEW , APP. View .DS.PLAT.DS.CTR.DS); 25 define( CTRONLLER , APP. Controller .DS.PLAT.DS); 27 $ctr = $c. Controller 29 spl_autoload_register( autoload //注冊(cè)自動(dòng)加載函數(shù) 30 //自動(dòng)加載類(lèi) 31 /** 32 * 實(shí)自動(dòng)加載類(lèi)文件 33 * @param string $className 類(lèi)名 34 */ 35 function autoload($className) 36 { 37 $upperClassName = strtoupper($className); 38 $frame = array( BaseController , BaseModel , Db , FactoryModel 39 if(in_array($className, $frame)) { //加載公共Frame目錄中的類(lèi)文件 40 require_once FRAME. $className.class.php 41 } elseif(substr($upperClassName, -5) == MODEL ){ //加載模型Model目錄中的類(lèi)文件 42 require_once MODEL. $className.class.php 43 } elseif(substr($upperClassName, -10) == CONTROLLER ){ //加載控制器目錄中的類(lèi)文件 44 require_once CTRONLLER. $className.class.php 45 } 46 } 48 //實(shí)例化控制器 49 $userCtr = new $ctr(); 50 $userCtr - $a();
2) 提交代碼
1 $ git add -A2 $ git commit -m 自動(dòng)加載類(lèi)完成優(yōu)化入口文件 思路
問(wèn)題: 此時(shí),入口文件代碼零碎增多,隨著后續(xù)代碼的增加,入口文件會(huì)更加臃腫復(fù)雜,不易管理
解決方法: 封裝入口文件中的操作稱(chēng)為一個(gè)類(lèi),這樣只需要在入口文件調(diào)用類(lèi)的方法即可
創(chuàng)建Init.class.php類(lèi)文件,放入到Frame中
將入口文件所有操作封裝成類(lèi)方法
loadClass() 設(shè)置自動(dòng)加載函數(shù)
autoload()自動(dòng)加載類(lèi)
setConst() 定義常量
dispatch() 前端分發(fā)器
1) 在Frame目錄中創(chuàng)建Init.class.php文件, 將入口文件index中的代碼復(fù)制進(jìn)行修改為類(lèi)
【Frame/Init.class.php】
1 ?php 2 /** 3 * 應(yīng)用初始化操作類(lèi) 4 * User: young 5 */ 7 class Init 8 { 9 protected static $frame = array( BaseController , BaseModel , Db , FactoryModel //Frame目錄公共操作類(lèi) 10 public static function run() 11 { 12 //平臺(tái) 13 self::dispatch(); 15 //定義常量 16 self::setConst(); 18 //自動(dòng)加載類(lèi) 19 self::loadClass(); 21 $ctr = CTR. Controller //拼接控制器名稱(chēng) 23 //實(shí)例化控制器 24 $ctrObj = new $ctr(); 25 $a = ACTION; 26 $ctrObj - $a(); 27 } 28 /** 29 * 設(shè)置自動(dòng)加載類(lèi)方法 30 */ 31 private static function loadClass() 32 { 33 spl_autoload_register( self::autoload 34 } 36 /** 37 * 實(shí)現(xiàn)自動(dòng)加載 38 * @param string $className 類(lèi)名 39 */ 40 private static function autoload($className) 41 { 42 $upperClassName = strtoupper($className); 43 if(in_array($className, static::$frame)) { 44 require_once FRAME. $className.class.php 45 } elseif(substr($upperClassName, -5) == MODEL ){ 46 require_once MODEL. $className.class.php 47 } elseif(substr($upperClassName, -10) == CONTROLLER ){ 48 require_once CTRONLLER. $className.class.php 49 } 50 } 52 /** 53 * 定義常量 54 */ 55 private static function setConst() 56 { 57 define( DS , DIRECTORY_SEPARATOR); //目錄分割符 58 define( ROOT , getcwd().DS); 59 define( FRAME , ROOT. Frame .DS); 60 define( APP , ROOT. App .DS); 61 define( PUB , ROOT. Public .DS); 62 define( ADMIN , PUB. Admin .DS); 63 define( HOME , PUB. Home .DS); 66 define( MODEL , APP. Model .DS); 67 define( VIEW , APP. View .DS.PLAT.DS.CTR.DS); 68 define( CTRONLLER , APP. Controller .DS.PLAT.DS); 69 } 71 /** 72 * 獲取 p c a 的GET值,并設(shè)置為常量 73 * @return void 74 */ 75 private static function dispatch() 76 { 77 $p = !empty($_GET[ p ]) ? $_GET[ p ] : Home //平臺(tái) 78 $c = !empty($_GET[ c ]) ? $_GET[ c ] : User //控制器 79 $a = !empty($_GET[ a ]) ? $_GET[ a ] : login //動(dòng)作 81 define( PLAT , $p); 82 define( CTR , $c); 83 define( ACTION , $a); 84 } 85 }
2) 入口文件引入初始化類(lèi),并調(diào)用其方法 【index.php】
1 ?php2 /**3 * 入口文件6 require_once ./Frame/Init.class.php 7 Init::run();
3) 提交代碼
1 $ git add -A2 $ git commit -m 優(yōu)化入口文件,封裝初始化類(lèi)安全訪問(wèn)項(xiàng)目目錄 思路
問(wèn)題: 此時(shí),項(xiàng)目中所有目錄都是可以通過(guò)瀏覽器訪問(wèn)的,如直接訪問(wèn)Frame/Db.class.php文件 直接可以去查看數(shù)據(jù)庫(kù)登錄信息,顯然是不安全的。
解決方法:
方式1: 在可以訪問(wèn)的文件開(kāi)始處定義常量,訪問(wèn)是判斷是否定義常量defined(..), 沒(méi)有定義指定常量則直接exit( Access Deny
方式2: 開(kāi)啟分布式權(quán)限配置,編寫(xiě).htaccess文件, 如禁止訪問(wèn), 將該文件放置在禁止訪問(wèn)的目錄中
實(shí)現(xiàn)1)使用上述方式2的形式來(lái)實(shí)現(xiàn), 站點(diǎn)配置中加入一項(xiàng)(環(huán)境搭建時(shí)已經(jīng)加入了): 詳細(xì)見(jiàn): PHP源碼搭建博客1-環(huán)境搭建
apache配置文件httpd-vhosts.conf 中站點(diǎn)配置
1 #允許分布式權(quán)限配置(允許重寫(xiě))(.htacess)2 AllowOverride All
2) 重啟apache后,編寫(xiě) .htaccess文件, 該文件內(nèi)容:
deny from all
3) 將.htaccess文件放置禁止訪問(wèn)的目錄中。 如App/ , Frame/ 目錄下。只用放在第一層即可,內(nèi)層目錄自動(dòng)不允許直接訪問(wèn)。
4) 訪問(wèn)測(cè)試
主要實(shí)現(xiàn)了 引入路徑優(yōu)化, 類(lèi)的自動(dòng)加載, 封裝優(yōu)化入口文件,目錄訪問(wèn)限制
MVC微型框架到此基本完成。其實(shí)還有很多還是可以繼續(xù)擴(kuò)展,如
1, 類(lèi)文件命名此處都用了 .class.php結(jié)尾, 實(shí)質(zhì)可以?xún)?yōu)化直接使用.php結(jié)尾
2, 引入命名空間,更方便的加載類(lèi)
3, 項(xiàng)目中出現(xiàn)錯(cuò)誤,此時(shí)是直接顯示在瀏覽器上的, 可以寫(xiě)一個(gè)日志類(lèi),發(fā)生錯(cuò)誤寫(xiě)入文件或數(shù)據(jù)庫(kù)都可
4, 數(shù)據(jù)庫(kù)連接信息此處是直接寫(xiě)在DB類(lèi)和BaseModel中了, 是不安全的。 可以創(chuàng)建一個(gè)配置目錄,將這些信息寫(xiě)入配置文件,再寫(xiě)一個(gè)加載配置文件的類(lèi)。
5. 此架構(gòu)目錄 ,是在C,V中分平臺(tái),如Controller/Home, Controller/Admin; 實(shí)際也可以寫(xiě)成 平臺(tái)下分MVC結(jié)構(gòu), 如Admin/Controller, Admin/Model, Home/Controller,Home/View .. 這個(gè)是比較靈活的,可以根據(jù)需求選擇更加合適的方式
實(shí)際上線項(xiàng)目,還是建議使用框架,安全快捷; 自己模仿定義的框架結(jié)構(gòu)適合學(xué)習(xí)研究使用,容易遺漏,造成安全隱患,操作不便等問(wèn)題
下一步:根據(jù)博客前端模板,分析創(chuàng)建數(shù)據(jù)表, 開(kāi)始搭建博客后臺(tái)程序,后續(xù)首先準(zhǔn)備實(shí)現(xiàn) “分類(lèi)模塊”。既分類(lèi)的展示,修改,添加,刪除功能
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,更多相關(guān)內(nèi)容請(qǐng)關(guān)注PHP !
相關(guān)推薦:
php源碼之區(qū)分平臺(tái)MVC結(jié)構(gòu)的介紹
php源碼之實(shí)現(xiàn)單入口MVC結(jié)構(gòu)的方法
以上就是php源碼之實(shí)現(xiàn)MVC結(jié)構(gòu)微型框架的詳細(xì)內(nèi)容,PHP教程
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。
新聞熱點(diǎn)
疑難解答
圖片精選