PHP CodeIgniter架構的工作原理研究_PHP教程

來源:互聯網
上載者:User

PHP CodeIgniter架構的工作原理研究


這篇文章主要介紹了PHP CodeIgniter架構的工作原理研究,本文首先分析了它的工作流程,然後總結了它的工作原理,需要的朋友可以參考下

CodeIgniter(以下簡稱CI,官網以及中國站)是一個流行的PHP架構,小巧但功能強大,簡潔輕量同時擁有很好的擴充性,在國內也比較受歡迎。另一方面,CI卻沒有與時俱進,並不支援PHP5.3之後的一些特性,導致它相對更適合較老一些的項目。雖然如此,CI仍是一個優秀的架構,而且它本身核心較小,源碼優雅,適於學習。

CI便於使用,可以方便的開發出web應用。先來看一下CI的工作流程圖(此處內容引用自http://codeigniter.org.cn/user_guide/overview/appflow.html)



1.index.php 作為前端控制器,初始化運行 CodeIgniter 所需要的基本資源。
2.Router 檢查 HTTP 請求,以確定誰來處理請求。
3.如果緩衝(Cache)檔案存在,它將繞過通常的系統執行順序,被直接發送給瀏覽器。
4.安全(Security)。應用程式控制器(Application Controller)裝載之前,HTTP 請求和任何使用者提交的資料將被過濾。
5.控制器(Controller)裝載模型、核心庫、輔助函數,以及任何處理特定請求所需的其它資源。
6.最終視圖(View)渲染髮送到 網頁瀏覽器中的內容。如果開啟緩衝(Caching),視圖首先被緩衝,所以將可用於以後的請求。

以上給出了一個大致流程。那麼當看到頁面在瀏覽器中呈現時,程式內部究竟是如何工作的呢?
下面按照執行順序,依次列出了CI架構主要載入的檔案,並簡要介紹其作用:

01. index.php
定義使用環境(ENVIRONMENT),架構路徑(system_path,BASEPATH),應用目錄(application_folder),應用路徑(APPPATH)等,載入(require)CI核心檔案
02. BASEPATH/core/CodeIgniter.php (ps.實際上BASEPATH包含最後的檔案分隔字元'/',這裡額外加上了'/'是為了更清晰的展示)
系統初始設定檔案,整個架構最核心的部分,在此載入(load)了一系列的base class,並且執行這次請求
03. BASEPATH/core/Common.php
common檔案包含一系列的基礎和公用函數 ,供全域使用,例如load_class(),get_config()等
04. BASEPATH/core/Benchmark
這是一個基準測試類別,預設標註了應用各個階段的執行點,以得到其執行時間。也允許你自己定義監測點。
05. BASEPATH/core/Hooks.php
CI_Hooks是一個鉤子類,是架構進行擴充的核心,能夠在程式允許的各個階段插入掛鈎點,執行你自訂的類,函數等
06. BASEPATH/core/Config.php
設定檔管理類,載入讀取或設定配置
07. BASEPATH/core/URI.php, BASEPATH/core/Router.php
URI類協助你解析請求的uri,並提供分割uri的函數集合,供Router類使用
08. BASEPATH/core/Router.php
路由類,即通過請求的uri,和使用者配置的路由(APPPATH/config/routes.php),將使用者請求分發到指定的處理函數中(通常來說是某一個Controller執行個體中某一action函數)
09. BASEPATH/core/Output.php, BASEPATH/core/Input.php
輸入類,即處理請求的輸入參數,提供安全的擷取方式。輸出類將最後的執行結果發送出去,它還負責緩衝的功能
10. BASEPATH/core/Controller.php
控制器基類,用單例模式對外提供執行個體,整個應用程式的心臟。它是一個Super Object,在應用內載入的類都可以成為控制器的成員變數,這一點非常重要,會在之後繼續 講到。
11. APPPATH/controllers/$RTR->fetch_directory().$RTR->fetch_class().'.php'
通過路由功能,得到控制器名,執行個體化真正的控制器類(子類)
12. BASEPATH/core/Loader.php
CI_Loader用於載入應用程式中的各種類庫,模型,視圖,資料庫,檔案等,並設定成為控制器的成員變數
13. call_user_func_array 調用處理函數
通過路由,得到action函數名,調用 Controller->action()函數,處理應用邏輯,實際業務處理邏輯便是在action函數中寫的
14. $OUT->_display() 將內容輸出

以上便是整個應用程式最基礎的處理流程。下面選取核心內容代碼再進行說明,以加強對CI的理解:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

//*BASEPATH/system/core/Common.php

//引導檔案中Benchmark,Hooks,Config等都是通過這個函數進行載入的

function &load_class($class, $directory = 'libraries', $prefix = 'CI_')

{

//記錄載入過的類

static $_classes = array();

// 已經載入過,直接讀取並返回

if (isset($_classes[$class]))

{

return $_classes[$class];

}

$name = FALSE;

// 在指定目錄尋找要載入的類

foreach (array(APPPATH, BASEPATH) as $path)

{

if (file_exists($path.$directory.'/'.$class.'.php'))

{

$name = $prefix.$class;

if (class_exists($name) === FALSE)

{

require($path.$directory.'/'.$class.'.php');

}

break;

}

}

// 沒有找到

if ($name === FALSE)

{

exit('Unable to locate the specified class: '.$class.'.php');

}

// 追蹤記錄下剛才載入的類,is_loaded()函數在下面

is_loaded($class);

$_classes[$class] = new $name();

return $_classes[$class];

}

// 記錄已經載入過的類。函數返回所有載入過的類

function &is_loaded($class = '')

{

static $_is_loaded = array();

if ($class != '')

{

$_is_loaded[strtolower($class)] = $class;

}

return $_is_loaded;

}

//*BASEPATH/system/core/Controller.php

class CI_Controller {

private static $instance;

public function __construct()

{

self::$instance =& $this;

//將所有在引導檔案中(CodeIgniter.php)初始化的類對象(即剛才4,5,6,7,8,9等步驟),

//註冊成為控制器類的成員變數,就使得這個控制器成為一個超級對象(super object)

foreach (is_loaded() as $var => $class)

{

$this->$var =& load_class($class);

}

//載入Loader對象,再利用Loader對象對程式內一系列資源進行載入

$this->load =& load_class('Loader', 'core');

$this->load->initialize();

log_message('debug', "Controller Class Initialized");

}

//這個函數對外提供了控制器的單一執行個體

public static function &get_instance()

{

return self::$instance;

}

}

//*BASEPATH/system/core/CodeIgniter.php

// Load the base controller class

require BASEPATH.'core/Controller.php';

//通過這個全域函數就得到了控制器的執行個體,得到了這個超級對象,

//意味著在程式其他地方調用這個函數,就能得到整個架構的控制權

function &get_instance()

{

return CI_Controller::get_instance();

}

// 載入對應的控制器類

// 注意:Router類會自動使用 router->_validate_request() 驗證控制器路徑

if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php'))

{

show_error('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.');

}

include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php');

$class = $RTR->fetch_class(); //Controller class name

$method = $RTR->fetch_method(); //action name

//.....

// 調用請求的函數

// uri中除了class/function之外的段也會被傳遞給調用的函數

call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));

//輸出最終的內容到瀏覽器

if ($EXT->_call_hook('display_override') === FALSE)

{

$OUT->_display();

}

//*BASEPATH/system/core/Loader.php

//看一個Loader類載入model的例子。這裡只列出了部分代碼

public function model($model, $name = '', $db_conn = FALSE)

{

$CI =& get_instance();

if (isset($CI->$name))

{

show_error('The model name you are loading is the name of a resource that is already being used: '.$name);

}

$model = strtolower($model);

//依次根據model類的path進行匹配,如果找到了就載入

foreach ($this->_ci_model_paths as $mod_path)

{

if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))

{

continue;

}

if ($db_conn !== FALSE AND ! class_exists('CI_DB'))

{

if ($db_conn === TRUE)

{

$db_conn = '';

}

$CI->load->database($db_conn, FALSE, TRUE);

}

if ( ! class_exists('CI_Model'))

{

load_class('Model', 'core');

}

require_once($mod_path.'models/'.$path.$model.'.php');

$model = ucfirst($model);

//這裡依然將model對象註冊成控制器類的成員變數。Loader在載入其他資源的時候也會這麼做

$CI->$name = new $model();

$this->_ci_models[] = $name;

return;

}

// couldn't find the model

show_error('Unable to locate the model you have specified: '.$model);

}

//*BASEPATH/system/core/Model.php

//__get()是一個魔術方法,當讀取一個未定義的變數的值時就會被調用

//如下是Model基類對__get()函數的一個實現,使得在Model類內,可以像直接在控制器類內一樣(例如$this->var的方式)去讀取它的變數

function __get($key)

{

$CI =& get_instance();

return $CI->$key;

http://www.bkjia.com/PHPjc/976533.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/976533.htmlTechArticlePHP CodeIgniter架構的工作原理研究 這篇文章主要介紹了PHP CodeIgniter架構的工作原理研究,本文首先分析了它的工作流程,然後總結了它的工作原...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.