標籤:function 演算法 url 渲染 總結 靈活 函數 做了 輸入
原文:http://www.cnblogs.com/zhenbianshu/p/5331165.html
前言
說到寫PHP的MVC架構,大家想到的第一個詞--“造輪子”,是的,一個還沒有深厚功力的程式員,寫出的PHP架構肯定不如那些出自大神們之手、經過時間和各種項目考驗的架構。但我還是準備並且這麼做了,主要是因為:
- 認為有關PHP的方方面面都瞭解了,但自己學習PHP的時間還短,基礎並不紮實,很多常用函數的參數還偶爾要查手冊,而且對於PHP的一些較新的特性如命名空間、反射等只是簡單的看過,並沒有能實際應用過。
- PHP的知識多且雜,一個普通的項目往住是商務邏輯代碼為主,而架構是一個能把這些知識點能融匯在一起的項目。
- 在自己寫一個架構的時候,也會參考一些我使用過的架構如TP/CI/YII等的源碼,在自己看源碼時也能協助自己理解架構,更容易接受以後要使用的架構。
所以說,這次造輪子的目的不是為了造輪子而是為了在造輪子的過程中熟悉其工藝,總結輪子特點,更好的使用輪子。
如果說寫一個完整的PHP架構,那需要掌握的PHP知識點非常多,像設計模式、迭代器、事件與鉤子等等,還有許多基礎知識的靈活應用。我自認為這些還無法完全掌控,所以我的步驟是先自己搭建一個骨架,然後參考借鑒不同的PHP架構的特點,將其慢慢完善。因為工作原因,而且晚上還要補演算法、網路等編程基礎,PHP架構部分可能只有周末有時間更新,我會在進行架構功能更新之後,總結使用的知識點,更新博文。
架構整體
首先自己總結一下PHP的MVC架構的工作流程:
簡單來說,它以一個入口檔案來接受請求,選擇路由,處理請求,返回結果。
當然,幾句話總結完的東西實際上要做的工作很多,PHP架構會在每次接受請求時,定義常量,載入設定檔、基礎類,根據訪問的URL進行邏輯判斷,選擇對應的(模組)控制器和方法,並且自動載入對應類,處理完請求後,架構會選擇並渲染對應的模板檔案,以html頁面的形式返迴響應。在處理邏輯的時候,還要考慮到錯誤和異常的處理。
1、作為MVC架構,一定要有一個唯一的入口檔案來統領全域,所有的訪問請求都會首先進入這個入口檔案,如我架構根目錄的index.php,在裡面,我定義了基本檔案夾路徑,當前環境,並根據當前環境定義錯誤報表的層級。
2、PHP中載入另外的檔案,使用require和include,它們都是將目標檔案內容載入到當前檔案內,替換掉require或include語句,require是載入進來就執行,而include是載入進來在需要的時候執行,而它們的_once結構都是表示在寫多次的時候只執行一次。
3、架構內的組態變數等使用專用的設定檔來儲存,這裡我仿照了TP裡的數組返回法,用了一個compileConf()函數來解析數組,將數組的鍵定義為常量,值為數組的值。
if (!function_exists(‘compile_conf‘)) { function compileConf($conf) { foreach ($conf as $key => $val) { if(is_array($val)){ compileConf($val); }else{ define($key, $val); } } } } compileConf(require_once CONF_PATH.‘config.php‘);
命名空間和自動載入
為什麼把命名空間和自動載入放到一塊說呢?
在一個PHP項目中,類特別多的時候,如果類名重複的話就會造成混亂,而且相同檔案夾內也不能存在同名的檔案,所以這時候命名空間和檔案夾就搭檔出場了。檔案夾就是一個一個的盒子,命名空間在我理解就像是一個標籤,盒子對應標籤。我們定義類時,把各種類用不同的盒子分別裝好,並貼上對應的標籤。而在自動載入類時,我們根據標籤(命名空間)可以很輕易找到對應的盒子(檔案夾)然後找到對應的類檔案。
而類的自動載入,我們知道的__autoload()魔術函數,它會在你執行個體化一個當前路徑找不到的對象時自動調用,根據傳入的類名,在函數體內載入對應的類檔案。
現在我們多用spl_autoload_register()函數,它可以註冊多個函數來代替__autoload函數的功能,我們傳入一個函數名為參數,spl_autoload_register會將這個函數壓入棧中,在執行個體化一個當前路徑內找不到的類時,系統將會將函數出棧依次調用,直到執行個體化成功。
spl_autoload_register(‘Sqier\Loader::autoLoad‘);class Loader {public static function autoLoad($class) { //如果有的話,去除類最左側的\ $class = ltrim($class, ‘\\‘); //擷取類的路徑全名 $class_path = str_replace(‘\\‘, ‘/‘, $class) . EXT; if (file_exists(SYS_PATH . $class_path)) { include SYS_PATH . $class_path; return; } if (file_exists(APP_PATH . $class_path)) { include APP_PATH . $class_path; return; }}
現在Loader類還是一個簡單的類,待以後慢慢完善。
路由選擇
接下來就是路由選擇了,其本質是根據當前定義的全域URL模式選擇合適的方法來分析傳入的URI,載入對應的類,並實現對應的方法。
class Router {public static $uri;public static function bootstrap() { self::$uri = $_SERVER[‘REQUEST_URI‘]; switch (URL_MODE) { case 1: { self::rBoot(); break; } default: { self::rBoot(); } }}public static function rBoot() { $router = isset($_GET[‘r‘]) ? explode(‘/‘, $_GET[‘r‘]) : [ ‘index‘, ‘index‘ ]; $cName = ‘Controller\\‘ . ucfirst($router[0]); $aName = isset($router[1]) ? strtolower($router[1]) . ‘Action‘ : ‘indexAction‘; $controller = new $cName(); $controller->$aName(); }}
這樣,我在地址欄輸入 zbs.com/index.php?r=index/login 後,系統會自動調用/app/Controller/Index.php下的login方法。完成了這麼一個簡單的路由。
搭建自己的PHP架構心得——轉載