一步一步重寫 CodeIgniter 框架 (4) —— load_class 管理多個對象實例的思路


我們使用CodeIgniter 框架最主要是想利用其 MVC 特性,將模型、視圖分開,並通過控制器進行統一控制。在嘗試實現 MVC 模式之前,我們將實現其中一個對程序結構非常有用的技巧,就是 load_class 函數。

在上一課中,我們用面向對象的方法大大簡化了程序的結構,將主要工作放在兩個類中進行 ,URI 和 Router 類。 但是在 Router 類的構造函數中為了獲得 uri 的實例,我們使用了 global 關鍵字,如下所示:

1 class CI_Router {
2     ...
3     function __construct() {
4         global $URI;
5         $this->uri = &$URI;
6     }
7         ....
8 }

當程序的結構變得很復雜時,用 global 關鍵詞會使得全局變量的管理非常亂,而且這些全局變量往往對應於一個具體功能類的實例,在實例化之前需要加載相應class的 php 文件。

1. 問題提煉和分析

  根據上述分析,關鍵的問題是

  1)需要一個集成管理這些全局變量的地方

  2)這些類的實例產生時,很方便的加載對應的 php 文件。

  集成管理變量一般采用 類的方式,然后通過該類的一個實例(唯一一個)獲取需要的變量,這個實例往往稱為核心全局變量,如discuz 中的 $discuz_core 變量;

  另一種方式,就是函數,但是函數沒法存儲成員變量,所以必須利用一個很有用的語法特性,就是 static 靜態變量。

  在這里,我們采用第二種更簡潔的方式。

2. 實現步驟

  1) 定義函數的接口

    函數名為 load_class , 我們希望通過傳遞一個字符串參數,就能獲得對應的實例,比如 load_class('Router'); 就可以得到 上一課中的 $RTR 變量的引用。

    所以函數的接口為:    

function &load_class($class) {}

  2) 定義存儲這些重要類實例全局變量的靜態數組 

static $_classes = array();

那么該數組,存儲的鍵值對就是 ’Router' => $RTR  的樣子。

  3) 具體的邏輯

 1 // 當加載需要的類實例時,如果不是第一次加載,那么 $_classes 數組中肯定存放了需要的實例,直接返回即可
 2     if (isset($_classes[$class])) {
 3         return $_classes[$class];
 4     }
 5 
 6     // 在我們的框架中,每個類實例都有前綴CI_
 7     $name = 'CI_'.$class;
 8 
 9     if (file_exists($class.'.php')) {
10         require($class.'.php');
11     } else {
12         exit('Unable to locate the class');
13     }
14 
15     $_classes[$class] = new $name();
16     return $_classes[$class];

3. 修改主邏輯代碼  

 1 <?php
 2 /**
 3  * 框架主入口文件,所有的頁面請求均定為到該頁面,並根據 url 地址來確定調用合適的方法並顯示輸出
 4  */
 5 require('Common.php');
 6 
 7 $URI =& load_class('URI');
 8 $RTR =& load_class('Router');
 9 
10 $RTR->set_routing();
11 
12 
13 $class = $RTR->fetch_class();
14 $method = $RTR->fetch_method();
15 
16 $CI = new $class();
17 
18 call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));
19 
20 class Welcome {
21 
22     function hello() {
23         echo 'My first Php Framework!';
24     }
25 
26     function saysomething($str) {
27         echo $str.", I'am the php framework you created!";
28     }
29 }

 另外,所有需要用到這些全局變量的地方,調用 load_class 就可以了,所以 Router 構造函數的地方使用 load_class.

1 function __construct() {
2     $this->uri =& load_class('URI');
3 }

4. 測試結果

  訪問 http://localhost/learn-ci/index.php/welcome/hello , 可以看到輸出為:

  hello, I'am the php framework you created!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM