php源碼之實現MVC結構微型架構

來源:互聯網
上載者:User
這篇文章主要介紹了關於php源碼之實現MVC結構微型架構,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

主要:

  1. 常量最佳化路徑

  2. 自動載入類

  3. 最佳化入口檔案

  4. 安全訪問項目目錄

----------------------------------------------------blog├─App│  ├─Model 模型│  │  └─UserModel.class.php 使用者模型類    │  ├─View 視圖│  │  ├─Back後台│  │  │  └─Index│  │  │          └─index.html  後台首頁面│  │  └─Home前台│  │      └─User 使用者視圖目錄│  │             └─login.html  登入表單頁面│  ├─Controller 控制器│  │  ├─Back後台│  │  │  └─IndexController.class.php 後台首頁控制器│  │  └─Home前台│  │      └─UserController.class.php 使用者控制器├─Public   靜態公用檔案(js,css,images)│  ├─Plugins 外掛程式│  │  └─layui 前端架構外掛程式│  ├─Back後台│  │    ├─js/   js檔案│  │    ├─css/  css樣式檔案│  │    └─image img圖片 │  └─Home前台│      ├─js/   js檔案│      ├─css/  css樣式檔案│      └─image img圖片 ├─Frame 公用使用的類│   ├─BaseModel.class.php 資料庫連接類│   ├─BaseController.class.php 控制器公用操作(設定編碼,資訊跳轉)│   ├─FactoryModel.class.php  模型工廠類│   ├─Init.class.php  初始化應用類│   └─MySQLDB.class.php 資料庫操作工具類└─index.php  入口檔案-----------------------------------------------------------------

上一篇中,提出4個問題待解決,本篇集中解決這4個問題,最終形成完整的微型MVC架構結構, 後續部落格項目,或其他項目,均可以直接使用該架構結構進行開發學習。

下載查看該項目源碼: https://gitee.com/NewbiesYang/young_blog

常量最佳化路徑

準備: 建立分支

1 $ git checkout master2 $ git checkout -b "MVC"

  思路

  1)把常用的目錄路徑定義成常量。如 模型目錄,控制器目錄等
 2)引入類使用定義的常量替代部分路徑。 如 include FRAME.BaseModel.class.php
3) 載入視圖使用常量替代部分路徑 如 include VIEW.'login.html' 簡單形式

  代碼實現

1)操作步驟

step 1: 在入口檔案中定義所需要的常量step 2: 控制器中引入視圖時, 使用常量進行最佳化

操作步驟思路

2) 入口檔案中定義常用路徑常量 【index.php】

 1 <?php  2 /**  3  * 入口檔案  4  */  5 $p = !empty($_GET['p']) ? $_GET['p'] : 'Home';  //平台  6 $c = !empty($_GET['c']) ? $_GET['c'] : 'User';  //控制器  7 $a = !empty($_GET['a']) ? $_GET['a'] : 'login'; //動作  8   9 define('PLAT', $p);  //平台常量 10 define('CTR', $c);  //控制器 11 define('ACTION', $a); //動作 12  13  14 define('DS', DIRECTORY_SEPARATOR); //目錄分割符 15 define('ROOT', getcwd().DS);  //當前所在目錄 項目目錄 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); 21  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); 26  27 $ctr = $c."Controller"; 28  29 require_once FRAME.'Db.class.php';  //資料庫操作類 30 require_once FRAME.'BaseModel.class.php';  //基本模型類 31 require_once MODEL.'UserModel.class.php';  //使用者模型類 32 require_once FRAME.'FactoryModel.class.php';//模型工廠類 33 require_once FRAME.'BaseController.class.php'; //基礎控制器類 34 require_once CTRONLLER.$ctr.'.class.php'; 35  36  37 //執行個體化控制器 38 $userCtr = new $ctr(); 39  40 $userCtr -> $a();

2) 常量的使用:

  後台首頁控制器【App/Controller/Admin/IndexController.class.php】

 1 <?php  2 /**  3  * IndexController控制器類  4  * 後台相關操作  5  * User: young  6  */  7   8 class IndexController extends BaseController  9 { 10     //展示後台首頁 11     public function index() 12     { 13         include VIEW.'index.html'; 14     } 15 }

後台首頁控制器引入視圖路徑修改

  使用者控制器 登入視圖引入路徑【App/Controller/Home/UserController.class.php】

 1 <?php  2 /**  3  * UserController.class.php 使用者控制器  4  */  5   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 "常量使用"

自動載入類

  思路

  問題: 入口檔案中已經require_once 引入6個類,既增加一個需要引入一個,容易遺漏,重複和出錯。

  解決方案:自動載入類檔案

     方式1: 使用自動載入類函數__autoload()可以實現自動載入
  方式2: 實際項目中,多人開發,根據實用性,更多的是使用 sql_autoload_register()註冊函數自動載入

  根據目錄的特點實現自動載入
  Model類檔案特點,以Model結尾的類名 substr($className,-5)
  Controller檔案特點: 以Controller結尾的類名, substr($class,-10)

    公用類: 類名沒有統一形式,可以將Fame下的公用類放入到數組中,然後判斷類是否在數組中, 從而自動載入該目錄下的類檔案

  代碼實現

  1) 入口檔案實作類別的自動載入

 1 <?php  2 /**  3  * 入口檔案  4  */  5 $p = !empty($_GET['p']) ? $_GET['p'] : 'Home';  //平台  6 $c = !empty($_GET['c']) ? $_GET['c'] : 'User';  //控制器  7 $a = !empty($_GET['a']) ? $_GET['a'] : 'login'; //動作  8   9 define('PLAT', $p);  //平台常量 10 define('CTR', $c);  //控制器 11 define('ACTION', $a); //動作 12  13  14 define('DS', DIRECTORY_SEPARATOR); //目錄分割符 15 define('ROOT', getcwd().DS);  //當前所在目錄 項目目錄 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); 21  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); 26  27 $ctr = $c."Controller"; 28  29 spl_autoload_register('autoload'); //註冊自動載入函數 30 //自動載入類 31 /** 32  * 實自動載入類檔案 33  * @param  string $className 類名 34  */ 35 function autoload($className) 36 { 37     $upperClassName = strtoupper($className); 38     $frame = array('BaseController','BaseModel','Db','FactoryModel'); 39     if(in_array($className, $frame)) {  //載入公用Frame目錄中的類檔案 40         require_once FRAME."$className.class.php"; 41     } elseif(substr($upperClassName, -5) == 'MODEL'){  //載入模型Model目錄中的類檔案 42         require_once MODEL."$className.class.php"; 43     } elseif(substr($upperClassName, -10) == 'CONTROLLER'){  //載入控制器目錄中的類檔案 44         require_once CTRONLLER."$className.class.php"; 45     } 46 } 47  48 //執行個體化控制器 49 $userCtr = new $ctr(); 50 $userCtr -> $a();

2) 提交代碼

1 $  git add -A2 $  git commit -m "自動載入類完成"

最佳化入口檔案

  思路

  問題: 此時,入口檔案代碼零碎增多,隨著後續代碼的增加,入口檔案會更加臃腫複雜,不易管理

  解決方案: 封裝入口檔案中的操作稱為一個類,這樣只需要在入口檔案調用類的方法即可

    建立Init.class.php類檔案,放入到Frame中
   將入口檔案所有操作封裝成類方法
loadClass() 設定自動載入函數
autoload()自動載入類
setConst() 定義常量
dispatch() 前端分發器

  代碼實現

  1) 在Frame目錄中建立Init.class.php檔案, 將入口檔案index中的代碼複製進行修改為類

  【Frame/Init.class.php】

 1 <?php  2 /**  3  * 應用初始化操作類  4  * User: young  5  */  6   7 class Init  8 {  9     protected static $frame = array('BaseController','BaseModel','Db','FactoryModel'); //Frame目錄公用操作類 10     public static function run() 11     { 12         //平台 13         self::dispatch(); 14  15         //定義常量 16         self::setConst(); 17  18         //自動載入類 19         self::loadClass(); 20  21         $ctr = CTR."Controller";  //拼接控制器名稱 22  23         //執行個體化控制器 24         $ctrObj = new $ctr(); 25         $a = ACTION; 26         $ctrObj -> $a(); 27     } 28     /** 29      * 設定自動載入類方法 30      */ 31     private static function loadClass() 32     { 33         spl_autoload_register('self::autoload'); 34     } 35  36     /** 37      * 實現自動載入 38      * @param  string $className 類名 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     } 51  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); 64  65  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     } 70  71     /** 72      * 擷取 p c a 的GET值,並設定為常量 73      * @return void 74      */ 75     private static function dispatch() 76     { 77         $p = !empty($_GET['p']) ? $_GET['p'] : 'Home';  //平台 78         $c = !empty($_GET['c']) ? $_GET['c'] : 'User';  //控制器 79         $a = !empty($_GET['a']) ? $_GET['a'] : 'login'; //動作 80  81         define('PLAT', $p); 82         define('CTR', $c); 83         define('ACTION', $a); 84     } 85 }

2) 入口檔案引入初始化類,並調用其方法 【index.php】

1 <?php2 /**3  * 入口檔案4  */5 6 require_once './Frame/Init.class.php';7 Init::run();

3) 提交代碼

1 $  git add -A2 $  git commit -m "最佳化入口檔案,封裝初始化類"

安全訪問項目目錄

  思路

  問題: 此時,項目中所有目錄都是可以通過瀏覽器訪問的,如直接存取Frame/Db.class.php檔案 直接可以去查看資料庫登入資訊,顯然是不安全的。

  解決方案:

    方式1: 在可以訪問的檔案開始處定義常量,訪問是判斷是否定義常量defined(..), 沒有定義指定常量則直接exit('Access Deny');

    方式2: 開啟分布式許可權配置,編寫.htaccess檔案, 如禁止訪問, 將該檔案放置在禁止訪問的目錄中

  實現

  1)使用上述方式2的形式來實現, 網站配置中加入一項(環境搭建時已經加入了): 詳細見: PHP源碼搭建部落格1-環境搭建

  apache設定檔httpd-vhosts.conf 中網站配置

1  #允許分布式許可權配置(允許重寫)(.htacess)2   AllowOverride All

  2) 重啟apache後,編寫 .htaccess檔案, 該檔案內容:

deny from all

  3) 將.htaccess檔案放置禁止訪問的目錄中。 如App/ , Frame/ 目錄下。只用放在第一層即可,內層目錄自動不允許直接存取。

  4) 訪問測試

小結:

主要實現了 引入路徑最佳化, 類的自動載入, 封裝最佳化入口檔案,目錄訪問限制

MVC微型架構到此基本完成。其實還有很多還是可以繼續擴充,如

  1, 類檔案命名此處都用了 .class.php結尾, 實質可以最佳化直接使用.php結尾

  2, 引入命名空間,更方便的載入類

3, 項目中出現錯誤,此時是直接顯示在瀏覽器上的, 可以寫一個日誌類,發生錯誤寫入檔案或資料庫都可

  4, 資料庫連接資訊此處是直接寫在DB類和BaseModel中了, 是不安全的。 可以建立一個配置目錄,將這些資訊寫入設定檔,再寫一個載入設定檔的類。

  5. 此架構目錄 ,是在C,V中分平台,如Controller/Home, Controller/Admin; 實際也可以寫成 平台下分MVC結構, 如Admin/Controller, Admin/Model, Home/Controller,Home/View .. 這個是比較靈活的,可以根據需求選擇更加合適的方式

  實際上線項目,還是建議使用架構,安全快捷; 自己模仿定義的架構結構適合學習研究使用,容易遺漏,造成安全隱患,操作不便等問題

下一步:根據部落格前端模板,分析建立資料表, 開始搭建部落格背景程式,後續首先準備實現 “分類別模組”。既分類的展示,修改,添加,刪除功能

以上就是本文的全部內容,希望對大家的學習有所協助,更多相關內容請關注topic.alibabacloud.com!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.