ThinkPHP框架完全解析五

第五步:實現Dispatcher,解析url

每一個框架都有其內置的庫文件,想要使用的時候,都需要使用include或者是require這兩條命令將庫文件引入進來。

然而,一個框架庫文件是相當多,一下子就使用好幾十條include或者是require不僅費時而且還費力,所以我們可以把這些文件定義在一個數組中,然後只要遍歷這個數組,然後一一require就可以了。

在tp框架中, ThinkPHP\Mode\common.php就是這麼一個文件,這個文件定義了一個二維數組,裏面存放了框架所需要使用的文件。

在我們自己實現的框架中,也新建這麼一個文件:

<?php

return array(

'core'=>array(

         LIB_PATH.'Think\App.class.php'

)

);

 

因此,在我們的Think.class.php這個文件中的:

require LIB_PATH.'Think\App.class.php';就可以直接替換成一條循環語句,用來將主要文件包含進來。

           $mode=include MODE_PATH.'common.php';

           foreach($mode['core'] as $file){

                if(is_file($file)){

                         include$file;

                }

           }

因此,現在start函數體爲:

         staticfunction start(){

                   //註冊AUTOLOAD方法

     spl_autoload_register('Think\Think::autoload');

          

           //讀取核心類庫

           $mode=include MODE_PATH.'common.php';

           foreach($mode['core'] as $file){

                if(is_file($file)){

                         include$file;

                }

           }

          

           App::run();

         }

這樣就可以快速地導入我們的框架文件,而不必要去寫autoload這個去自動載入,因爲使用這個自動載入需要解析,會花費比較長的時間。

現在,轉入到我們今天的主題,實現dispatcher這個類。

首先,Think.class.php同一目錄下新建一個Dispatcher.class.php這個文件。因爲在上一步驟中,我們只是簡單地實現url模式,但是卻功能簡單和不安全,因此,我們將解析url的功能,也就是在上一步驟中app類中exec這個函數中的內容轉移到dispatcher這個類中去。將解析功能單獨設計成一個類,好處是相當多,因爲這樣的話,擴展解析功能就比較容易,並且也符合面向對象的設計思想。

<?php

namespace Think;

 

class Dispatcher{

         staticfunction dispatch(){

                   if(isset($_SERVER['PATH_INFO'])){

                            $url=$_SERVER['PATH_INFO'];

                            $str=explode('/',trim($url,'/'));

                   }

                   $MOD=ucfirst(!empty($str[0])?$str[0]:'Home');

                   $CON=ucfirst(!empty($str[1])?$str[1]:'index').'Controller';

                   $ACT=ucfirst(!empty($str[2])?$str[2]:'index');

 

                   define('MODULE_NAME',$MOD);

                   define('CONTROLLER_NAME',$CON);

                   define('ACTION_NAME',$ACT);

         }

}

在這裏,不同的是將最後的實例化類變成了定義常量。因爲dispatcher這個類的主要功能是解析url,而不是執行url,因此,我們將其定義爲常量。這個,在app中的類就可以使用這三個常量了。並且因爲idpatcher中解析函數dispatch是一個靜態的成員函數,因此我們可以在app::init中運行這個函數,然後再在exec中實例類。

所以當前的app.class.php文件變爲:

<?php

namespace Think;

 

class App{

         staticfunction run(){

                   //環境初始化

                   self::init();

                   self::exec();

         }

 

         staticfunction init(){

                   //解析url

                   Dispatcher::dispatch();

         }

        

         staticfunction exec(){

                   //MODULE_NAME都是在dispatcher這個類中被定義的。

                   $namespace=MODULE_NAME.'\\Controller\\';

                   $class=$namespace.CONTROLLER_NAME;

                   //與上一步操作一樣,實例化類,並且執行類中的操作

                   $module=new$class;

                   $act=ACTION_NAME;

                   $module->$act();

        

         }

}

在init中需要運行dispatcher這個類,但是包含這個文件的類我們並沒有包含,因此我們需要在最開始我們新建的那個common.php這個文件中引入:

<?php

return array(

'core'=>array(

         LIB_PATH.'Think\App.class.php',

         LIB_PATH.'Think\Dispatcher.class.php',

)

);

運行效果如下圖:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章