无聊,决定水一把。
CI(CodeIgniter)是我最早接触的一个框架,到现在也只是用了其中一点零碎的方法。一直想对其流程做个小结,却总是因各种各样的“理由”挨着。看见别人图表齐上阵,没那耐心,就从代码说起吧,权当做个笔记,纪念一下。
看在线的用户手册,也知道,将CI下载下来(最新版本2.2.1),解压到机子上,比如www目录,可改个根目录名(原名CodeIgniter-2.2-stable太长),初步目录文件如下,当然这在是windows下面。
访问下,如localhost/ci/index.php,就进入CI默认的Welcome页面
如何一步步加载这个页面的?首先访问的是index.php脚本
<span> 1</span> <?<span>php </span><span> 2</span> <span> 3</span> <span>/*</span> <span> 4</span> <span> *--------------------------------------------------------------- </span><span> 5</span> <span> * APPLICATION ENVIRONMENT </span><span> 6</span> <span> *--------------------------------------------------------------- </span><span> 7</span> <span> * </span><span> 8</span> <span> * You can load different configurations depending on your </span><span> 9</span> <span> * current environment. Setting the environment also influences </span><span> 10</span> <span> * things like logging and error reporting. </span><span> 11</span> <span> * </span><span> 12</span> <span> * This can be set to anything, but default usage is: </span><span> 13</span> <span> * </span><span> 14</span> <span> * development </span><span> 15</span> <span> * testing </span><span> 16</span> <span> * production </span><span> 17</span> <span> * </span><span> 18</span> <span> * NOTE: If you change these, also change the error_reporting() code below </span><span> 19</span> <span> * </span><span> 20</span> <span>*/</span> <span> 21</span> <span>define</span>('ENVIRONMENT', 'development'<span>); </span><span> 22</span> <span>/*</span> <span> 23</span> <span> *--------------------------------------------------------------- </span><span> 24</span> <span> * ERROR REPORTING </span><span> 25</span> <span> *--------------------------------------------------------------- </span><span> 26</span> <span> * </span><span> 27</span> <span> * Different environments will require different levels of error reporting. </span><span> 28</span> <span> * By default development will show errors but testing and live will hide them. </span><span> 29</span> <span>*/</span> <span> 30</span> <span> 31</span> <span>if</span> (<span>defined</span>('ENVIRONMENT'<span>)) </span><span> 32</span> <span>{ </span><span> 33</span> <span>switch</span><span> (ENVIRONMENT) </span><span> 34</span> <span> { </span><span> 35</span> <span>case</span> 'development': <span> 36</span> <span>error_reporting</span>(<span>E_ALL</span><span>); </span><span> 37</span> <span>break</span><span>; </span><span> 38</span> <span> 39</span> <span>case</span> 'testing': <span> 40</span> <span>case</span> 'production': <span> 41</span> <span>error_reporting</span>(0<span>); </span><span> 42</span> <span>break</span><span>; </span><span> 43</span> <span> 44</span> <span>default</span>: <span> 45</span> <span>exit</span>('The application environment is not set correctly.'<span>); </span><span> 46</span> <span> } </span><span> 47</span> <span>} </span><span> 48</span> <span> 49</span> <span>/*</span> <span> 50</span> <span> *--------------------------------------------------------------- </span><span> 51</span> <span> * SYSTEM FOLDER NAME </span><span> 52</span> <span> *--------------------------------------------------------------- </span><span> 53</span> <span> * </span><span> 54</span> <span> * This variable must contain the name of your "system" folder. </span><span> 55</span> <span> * Include the path if the folder is not in the same directory </span><span> 56</span> <span> * as this file. </span><span> 57</span> <span> * </span><span> 58</span> <span>*/</span> <span> 59</span> <span>$system_path</span> = 'system'<span>; </span><span> 60</span> <span> 61</span> <span>/*</span> <span> 62</span> <span> *--------------------------------------------------------------- </span><span> 63</span> <span> * APPLICATION FOLDER NAME </span><span> 64</span> <span> *--------------------------------------------------------------- </span><span> 65</span> <span> * </span><span> 66</span> <span> * If you want this front controller to use a different "application" </span><span> 67</span> <span> * folder then the default one you can set its name here. The folder </span><span> 68</span> <span> * can also be renamed or relocated anywhere on your server. If </span><span> 69</span> <span> * you do, use a full server path. For more info please see the user guide: </span><span> 70</span> <span> * http://codeigniter.com/user_guide/general/managing_apps.html </span><span> 71</span> <span> * </span><span> 72</span> <span> * NO TRAILING SLASH! </span><span> 73</span> <span> * </span><span> 74</span> <span>*/</span> <span> 75</span> <span>$application_folder</span> = 'application'<span>; </span><span> 76</span> <span> 77</span> <span>/*</span> <span> 78</span> <span> * -------------------------------------------------------------------- </span><span> 79</span> <span> * DEFAULT CONTROLLER </span><span> 80</span> <span> * -------------------------------------------------------------------- </span><span> 81</span> <span> * </span><span> 82</span> <span> * Normally you will set your default controller in the routes.php file. </span><span> 83</span> <span> * You can, however, force a custom routing by hard-coding a </span><span> 84</span> <span> * specific controller class/function here. For most applications, you </span><span> 85</span> <span> * WILL NOT set your routing here, but it's an option for those </span><span> 86</span> <span> * special instances where you might want to override the standard </span><span> 87</span> <span> * routing in a specific front controller that shares a common CI installation. </span><span> 88</span> <span> * </span><span> 89</span> <span> * IMPORTANT: If you set the routing here, NO OTHER controller will be </span><span> 90</span> <span> * callable. In essence, this preference limits your application to ONE </span><span> 91</span> <span> * specific controller. Leave the function name blank if you need </span><span> 92</span> <span> * to call functions dynamically via the URI. </span><span> 93</span> <span> * </span><span> 94</span> <span> * Un-comment the $routing array below to use this feature </span><span> 95</span> <span> * </span><span> 96</span> <span>*/</span> <span> 97</span> <span>//</span><span> The directory name, relative to the "controllers" folder. Leave blank </span><span> 98</span> <span> // if your controller is not in a sub-folder within the "controllers" folder </span><span> 99</span> <span> // $routing['directory'] = ''; </span><span>100</span> <span>101</span> <span> // The controller class file name. Example: Mycontroller </span><span>102</span> <span> // $routing['controller'] = ''; </span><span>103</span> <span>104</span> <span> // The controller function you wish to be called. </span><span>105</span> <span> // $routing['function'] = '';</span> <span>106</span> <span>107</span> <span>108</span> <span>/*</span> <span>109</span> <span> * ------------------------------------------------------------------- </span><span>110</span> <span> * CUSTOM CONFIG VALUES </span><span>111</span> <span> * ------------------------------------------------------------------- </span><span>112</span> <span> * </span><span>113</span> <span> * The $assign_to_config array below will be passed dynamically to the </span><span>114</span> <span> * config class when initialized. This allows you to set custom config </span><span>115</span> <span> * items or override any default config values found in the config.php file. </span><span>116</span> <span> * This can be handy as it permits you to share one application between </span><span>117</span> <span> * multiple front controller files, with each file containing different </span><span>118</span> <span> * config values. </span><span>119</span> <span> * </span><span>120</span> <span> * Un-comment the $assign_to_config array below to use this feature </span><span>121</span> <span> * </span><span>122</span> <span>*/</span> <span>123</span> <span>//</span><span> $assign_to_config['name_of_config_item'] = 'value of config item'; </span><span>124</span> <span>125</span> <span>126</span> <span>127</span> <span>// -------------------------------------------------------------------- </span><span>128</span> <span>// END OF USER CONFIGURABLE SETTINGS. DO NOT EDIT BELOW THIS LINE </span><span>129</span> <span>// --------------------------------------------------------------------</span> <span>130</span> <span>131</span> <span>/*</span> <span>132</span> <span> * --------------------------------------------------------------- </span><span>133</span> <span> * Resolve the system path for increased reliability </span><span>134</span> <span> * --------------------------------------------------------------- </span><span>135</span> <span>*/</span> <span>136</span> <span>137</span> <span>//</span><span> Set the current directory correctly for CLI requests</span> <span>138</span> <span>if</span> (<span>defined</span>('STDIN'<span>)) </span><span>139</span> <span> { </span><span>140</span> <span>chdir</span>(<span>dirname</span>(<span>__FILE__</span><span>)); </span><span>141</span> <span> } </span><span>142</span> <span>143</span> <span>if</span> (<span>realpath</span>(<span>$system_path</span>) !== <span>FALSE</span><span>) </span><span>144</span> <span> { </span><span>145</span> <span>$system_path</span> = <span>realpath</span>(<span>$system_path</span>).'/'<span>; </span><span>146</span> <span> } </span><span>147</span> <span>148</span> <span>//</span><span> ensure there's a trailing slash</span> <span>149</span> <span>$system_path</span> = <span>rtrim</span>(<span>$system_path</span>, '/').'/'<span>; </span><span>150</span> <span>151</span> <span>//</span><span> Is the system path correct?</span> <span>152</span> <span>if</span> ( ! <span>is_dir</span>(<span>$system_path</span><span>)) </span><span>153</span> <span> { </span><span>154</span> <span>exit</span>("Your system folder path does not appear to be set correctly. Please open the following file and correct this: ".<span>pathinfo</span>(<span>__FILE__</span>,<span> PATHINFO_BASENAME)); </span><span>155</span> <span> } </span><span>156</span> <span>157</span> <span>/*</span> <span>158</span> <span> * ------------------------------------------------------------------- </span><span>159</span> <span> * Now that we know the path, set the main path constants </span><span>160</span> <span> * ------------------------------------------------------------------- </span><span>161</span> <span>*/</span> <span>162</span> <span>//</span><span> The name of THIS file</span> <span>163</span> <span>define</span>('SELF', <span>pathinfo</span>(<span>__FILE__</span>,<span> PATHINFO_BASENAME)); </span><span>164</span> <span>165</span> <span>//</span><span> The PHP file extension </span><span>166</span> <span> // this global constant is deprecated.</span> <span>167</span> <span>define</span>('EXT', '.php'<span>); </span><span>168</span> <span>169</span> <span>//</span><span> Path to the system folder</span> <span>170</span> <span>define</span>('BASEPATH', <span>str_replace</span>("\\", "/", <span>$system_path</span><span>)); </span><span>171</span> <span>172</span> <span>//</span><span> Path to the front controller (this file)</span> <span>173</span> <span>define</span>('FCPATH', <span>str_replace</span>(SELF, '', <span>__FILE__</span><span>)); </span><span>174</span> <span>175</span> <span>//</span><span> Name of the "system folder"</span> <span>176</span> <span>define</span>('SYSDIR', <span>trim</span>(<span>strrchr</span>(<span>trim</span>(BASEPATH, '/'), '/'), '/'<span>)); </span><span>177</span> <span>178</span> <span>179</span> <span>//</span><span> The path to the "application" folder</span> <span>180</span> <span>if</span> (<span>is_dir</span>(<span>$application_folder</span><span>)) </span><span>181</span> <span> { </span><span>182</span> <span>define</span>('APPPATH', <span>$application_folder</span>.'/'<span>); </span><span>183</span> <span> } </span><span>184</span> <span>else</span> <span>185</span> <span> { </span><span>186</span> <span>if</span> ( ! <span>is_dir</span>(BASEPATH.<span>$application_folder</span>.'/'<span>)) </span><span>187</span> <span> { </span><span>188</span> <span>exit</span>("Your application folder path does not appear to be set correctly. Please open the following file and correct this: ".<span>SELF); </span><span>189</span> <span> } </span><span>190</span> <span>191</span> <span>define</span>('APPPATH', BASEPATH.<span>$application_folder</span>.'/'<span>); </span><span>192</span> <span> } </span><span>193</span> <span>194</span> <span>/*</span> <span>195</span> <span> * -------------------------------------------------------------------- </span><span>196</span> <span> * LOAD THE BOOTSTRAP FILE </span><span>197</span> <span> * -------------------------------------------------------------------- </span><span>198</span> <span> * </span><span>199</span> <span> * And away we go... </span><span>200</span> <span> * </span><span>201</span> <span>*/</span> <span>202</span> <span>require_once</span> BASEPATH.'core/CodeIgniter.php'<span>; </span><span>203</span> <span>204</span> <span>/*</span><span> End of file index.php </span><span>*/</span> <span>205</span> <span>/*</span><span> Location: ./index.php </span><span>*/</span>View Code
21行:首先定义一个ENVIRONMENT常量为development,即开发环境。
31-47行:switch语句,由于当前环境是development,所以是设置报告所有级别的错误。
49-59行:$system_path变量定义CI的默认的系统脚本目录是 system,61-75行定义当前默认的供我们主要开发用的目录为 application。
77-105行:全部注释掉了,这里是我们可以强制设置系统加载时默认的目录名($routing['directory'])、控制器名($routing['directory'])和方法名($routing['directory']),虽然一般这些是设置在application\config\routes.php中(下图),访问的Welcome页面也是通过这个默认控制器Welcome类进行的,这里只是作为一个选择性的方式,其实没必要弄
108-129行:全部注释掉,用于自定义配置变量(CUSTOM CONFIG VALUES),前一篇说过,任何后端project中,总有些配置信息,只是各个项目或框架加载方式不同,这个$assign_to_config数组就存放我们的自定义配置信息,如$assign_to_config['home'] = 'localhost'; ,之所以注释掉,又是因为这只是一个可选的操作,CI的用户自定义配置信息,一般放在application\config目录下边,以自动加载信息(autoload.php),普通配置信息(config.php)、常量(constants.php)、数据库(database.php)等分开文件存储,所以一般不会在这里的去配置一个要用到的变量,$assign_to_config默认是没有定义的。
从131行到index.php文件末尾主要是对一些路径变量的定义。
137-141行:是为CLI(Command-Interface Line)的调用方式准备的,是直接在Mac/Linux系统上通过终端命令运行脚本,这个在CI中文官网(http://codeigniter.org.cn/user_guide/general/cli.html)也有介绍,如果定义了名为STDIN的常量,则将执行目录改为当前文件所在目录,当然前面没有出现过STDIN这个常量的定义,这里就不会执行了。
143-155行:确定框架存放系统脚本的目录变量$system_path,也就是前面图中的system目录,这里会检测它的有效性,无效的话程序就挂在这里了。
157-192行:定义若干主要目录常量,分别是SELF:当前脚本的文件名、EXT:脚本扩展名、BASEPATH:system目录的路径、FCPATH:当前脚本所在的目录、SYSDIR:system目录的目录名,不改动的话就是system。
179-194行:定义APPPATH常量,确定application所在的目录,就是以后我们主要开发的地方,使用is_dir检测,稍微注意的是is_dir可以检测相对目录,所以实际运行的是if里边的代码,APPPATH得到的是相对路径。
最后打印看看这些变(常)量的值都是啥,有的与存放目录相关:
202行:加载BASEPATH.'core/CodeIgniter.php'脚本,就是system目录下的核心类文件目录下的文件,进入到CI的核心类目录下的文件了。
=====================================================================================================
<span> 1</span> <?php <span>if</span> ( ! <span>defined</span>('BASEPATH')) <span>exit</span>('No direct script access allowed'<span>); </span><span> 2</span> <span>/*</span><span>* </span><span> 3</span> <span> * CodeIgniter </span><span> 4</span> <span> * </span><span> 5</span> <span> * An open source application development framework for PHP 5.1.6 or newer </span><span> 6</span> <span> * </span><span> 7</span> <span> * @package CodeIgniter </span><span> 8</span> <span> * @author EllisLab Dev Team </span><span> 9</span> <span> * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. </span><span> 10</span> <span> * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/) </span><span> 11</span> <span> * @license http://codeigniter.com/user_guide/license.html </span><span> 12</span> <span> * @link http://codeigniter.com </span><span> 13</span> <span> * @since Version 1.0 </span><span> 14</span> <span> * @filesource </span><span> 15</span> <span>*/</span> <span> 16</span> <span> 17</span> <span>//</span><span> ------------------------------------------------------------------------</span> <span> 18</span> <span> 19</span> <span>/*</span><span>* </span><span> 20</span> <span> * System Initialization File </span><span> 21</span> <span> * </span><span> 22</span> <span> * Loads the base classes and executes the request. </span><span> 23</span> <span> * </span><span> 24</span> <span> * @package CodeIgniter </span><span> 25</span> <span> * @subpackage codeigniter </span><span> 26</span> <span> * @category Front-controller </span><span> 27</span> <span> * @author EllisLab Dev Team </span><span> 28</span> <span> * @link http://codeigniter.com/user_guide/ </span><span> 29</span> <span>*/</span> <span> 30</span> <span> 31</span> <span>/*</span><span>* </span><span> 32</span> <span> * CodeIgniter Version </span><span> 33</span> <span> * </span><span> 34</span> <span> * @var string </span><span> 35</span> <span> * </span><span> 36</span> <span>*/</span> <span> 37</span> <span>define</span>('CI_VERSION', '2.2.1'<span>); </span><span> 38</span> <span> 39</span> <span>/*</span><span>* </span><span> 40</span> <span> * CodeIgniter Branch (Core = TRUE, Reactor = FALSE) </span><span> 41</span> <span> * </span><span> 42</span> <span> * @var boolean </span><span> 43</span> <span> * </span><span> 44</span> <span>*/</span> <span> 45</span> <span>define</span>('CI_CORE', <span>FALSE</span><span>); </span><span> 46</span> <span> 47</span> <span>/*</span> <span> 48</span> <span> * ------------------------------------------------------ </span><span> 49</span> <span> * Load the global functions </span><span> 50</span> <span> * ------------------------------------------------------ </span><span> 51</span> <span>*/</span> <span> 52</span> <span>require</span>(BASEPATH.'core/Common.php'<span>); </span><span> 53</span> <span> 54</span> <span>/*</span> <span> 55</span> <span> * ------------------------------------------------------ </span><span> 56</span> <span> * Load the framework constants </span><span> 57</span> <span> * ------------------------------------------------------ </span><span> 58</span> <span>*/</span> <span> 59</span> <span>if</span> (<span>defined</span>('ENVIRONMENT') AND <span>file_exists</span>(APPPATH.'config/'.ENVIRONMENT.'/constants.php'<span>)) </span><span> 60</span> <span> { </span><span> 61</span> <span>require</span>(APPPATH.'config/'.ENVIRONMENT.'/constants.php'<span>); </span><span> 62</span> <span> } </span><span> 63</span> <span>else</span> <span> 64</span> <span> { </span><span> 65</span> <span>require</span>(APPPATH.'config/constants.php'<span>); </span><span> 66</span> <span> } </span><span> 67</span> <span> 68</span> <span>/*</span> <span> 69</span> <span> * ------------------------------------------------------ </span><span> 70</span> <span> * Define a custom error handler so we can log PHP errors </span><span> 71</span> <span> * ------------------------------------------------------ </span><span> 72</span> <span>*/</span> <span> 73</span> <span>set_error_handler</span>('_exception_handler'<span>); </span><span> 74</span> <span> 75</span> <span>if</span> ( ! is_php('5.3'<span>)) </span><span> 76</span> <span> { </span><span> 77</span> @<span>set_magic_quotes_runtime</span>(0); <span>//</span><span> Kill magic quotes</span> <span> 78</span> <span> } </span><span> 79</span> <span> 80</span> <span>/*</span> <span> 81</span> <span> * ------------------------------------------------------ </span><span> 82</span> <span> * Set the subclass_prefix </span><span> 83</span> <span> * ------------------------------------------------------ </span><span> 84</span> <span> * </span><span> 85</span> <span> * Normally the "subclass_prefix" is set in the config file. </span><span> 86</span> <span> * The subclass prefix allows CI to know if a core class is </span><span> 87</span> <span> * being extended via a library in the local application </span><span> 88</span> <span> * "libraries" folder. Since CI allows config items to be </span><span> 89</span> <span> * overriden via data set in the main index. php file, </span><span> 90</span> <span> * before proceeding we need to know if a subclass_prefix </span><span> 91</span> <span> * override exists. If so, we will set this value now, </span><span> 92</span> <span> * before any classes are loaded </span><span> 93</span> <span> * Note: Since the config file data is cached it doesn't </span><span> 94</span> <span> * hurt to load it here. </span><span> 95</span> <span>*/</span> <span> 96</span> <span>if</span> (<span>isset</span>(<span>$assign_to_config</span>['subclass_prefix']) AND <span>$assign_to_config</span>['subclass_prefix'] != ''<span>) </span><span> 97</span> <span> { </span><span> 98</span> get_config(<span>array</span>('subclass_prefix' => <span>$assign_to_config</span>['subclass_prefix'<span>])); </span><span> 99</span> <span> } </span><span>100</span> <span>101</span> <span>/*</span> <span>102</span> <span> * ------------------------------------------------------ </span><span>103</span> <span> * Set a liberal script execution time limit </span><span>104</span> <span> * ------------------------------------------------------ </span><span>105</span> <span>*/</span> <span>106</span> <span>if</span> (<span>function_exists</span>("set_time_limit") == <span>TRUE</span> AND @<span>ini_get</span>("safe_mode") == 0<span>) </span><span>107</span> <span> { </span><span>108</span> @<span>set_time_limit</span>(300<span>); </span><span>109</span> <span> } </span><span>110</span> <span>111</span> <span>/*</span> <span>112</span> <span> * ------------------------------------------------------ </span><span>113</span> <span> * Start the timer... tick tock tick tock... </span><span>114</span> <span> * ------------------------------------------------------ </span><span>115</span> <span>*/</span> <span>116</span> <span>$BM</span> =& load_class('Benchmark', 'core'<span>); </span><span>117</span> <span>$BM</span>->mark('total_execution_time_start'<span>); </span><span>118</span> <span>$BM</span>->mark('loading_time:_base_classes_start'<span>); </span><span>119</span> <span>120</span> <span>/*</span> <span>121</span> <span> * ------------------------------------------------------ </span><span>122</span> <span> * Instantiate the hooks class </span><span>123</span> <span> * ------------------------------------------------------ </span><span>124</span> <span>*/</span> <span>125</span> <span>$EXT</span> =& load_class('Hooks', 'core'<span>); </span><span>126</span> <span>127</span> <span>/*</span> <span>128</span> <span> * ------------------------------------------------------ </span><span>129</span> <span> * Is there a "pre_system" hook? </span><span>130</span> <span> * ------------------------------------------------------ </span><span>131</span> <span>*/</span> <span>132</span> <span>$EXT</span>->_call_hook('pre_system'<span>); </span><span>133</span> <span>134</span> <span>/*</span> <span>135</span> <span> * ------------------------------------------------------ </span><span>136</span> <span> * Instantiate the config class </span><span>137</span> <span> * ------------------------------------------------------ </span><span>138</span> <span>*/</span> <span>139</span> <span>$CFG</span> =& load_class('Config', 'core'<span>); </span><span>140</span> <span>141</span> <span>//</span><span> Do we have any manually set config items in the index.php file?</span> <span>142</span> <span>if</span> (<span>isset</span>(<span>$assign_to_config</span><span>)) </span><span>143</span> <span> { </span><span>144</span> <span>$CFG</span>->_assign_to_config(<span>$assign_to_config</span><span>); </span><span>145</span> <span> } </span><span>146</span> <span>147</span> <span>/*</span> <span>148</span> <span> * ------------------------------------------------------ </span><span>149</span> <span> * Instantiate the UTF-8 class </span><span>150</span> <span> * ------------------------------------------------------ </span><span>151</span> <span> * </span><span>152</span> <span> * Note: Order here is rather important as the UTF-8 </span><span>153</span> <span> * class needs to be used very early on, but it cannot </span><span>154</span> <span> * properly determine if UTf-8 can be supported until </span><span>155</span> <span> * after the Config class is instantiated. </span><span>156</span> <span> * </span><span>157</span> <span>*/</span> <span>158</span> <span>159</span> <span>$UNI</span> =& load_class('Utf8', 'core'<span>); </span><span>160</span> <span>161</span> <span>/*</span> <span>162</span> <span> * ------------------------------------------------------ </span><span>163</span> <span> * Instantiate the URI class </span><span>164</span> <span> * ------------------------------------------------------ </span><span>165</span> <span>*/</span> <span>166</span> <span>$URI</span> =& load_class('URI', 'core'<span>); </span><span>167</span> <span>168</span> <span>/*</span> <span>169</span> <span> * ------------------------------------------------------ </span><span>170</span> <span> * Instantiate the routing class and set the routing </span><span>171</span> <span> * ------------------------------------------------------ </span><span>172</span> <span>*/</span> <span>173</span> <span>$RTR</span> =& load_class('Router', 'core'<span>); </span><span>174</span> <span>$RTR</span>-><span>_set_routing(); </span><span>175</span> <span>176</span> <span>//</span><span> Set any routing overrides that may exist in the main index file</span> <span>177</span> <span>if</span> (<span>isset</span>(<span>$routing</span><span>)) </span><span>178</span> <span> { </span><span>179</span> <span>$RTR</span>->_set_overrides(<span>$routing</span><span>); </span><span>180</span> <span> } </span><span>181</span> <span>182</span> <span>/*</span> <span>183</span> <span> * ------------------------------------------------------ </span><span>184</span> <span> * Instantiate the output class </span><span>185</span> <span> * ------------------------------------------------------ </span><span>186</span> <span>*/</span> <span>187</span> <span>$OUT</span> =& load_class('Output', 'core'<span>); </span><span>188</span> <span>189</span> <span>/*</span> <span>190</span> <span> * ------------------------------------------------------ </span><span>191</span> <span> * Is there a valid cache file? If so, we're done... </span><span>192</span> <span> * ------------------------------------------------------ </span><span>193</span> <span>*/</span> <span>194</span> <span>if</span> (<span>$EXT</span>->_call_hook('cache_override') === <span>FALSE</span><span>) </span><span>195</span> <span> { </span><span>196</span> <span>if</span> (<span>$OUT</span>->_display_cache(<span>$CFG</span>, <span>$URI</span>) == <span>TRUE</span><span>) </span><span>197</span> <span> { </span><span>198</span> <span>exit</span><span>; </span><span>199</span> <span> } </span><span>200</span> <span> } </span><span>201</span> <span>202</span> <span>/*</span> <span>203</span> <span> * ----------------------------------------------------- </span><span>204</span> <span> * Load the security class for xss and csrf support </span><span>205</span> <span> * ----------------------------------------------------- </span><span>206</span> <span>*/</span> <span>207</span> <span>$SEC</span> =& load_class('Security', 'core'<span>); </span><span>208</span> <span>209</span> <span>/*</span> <span>210</span> <span> * ------------------------------------------------------ </span><span>211</span> <span> * Load the Input class and sanitize globals </span><span>212</span> <span> * ------------------------------------------------------ </span><span>213</span> <span>*/</span> <span>214</span> <span>$IN</span> =& load_class('Input', 'core'<span>); </span><span>215</span> <span>216</span> <span>/*</span> <span>217</span> <span> * ------------------------------------------------------ </span><span>218</span> <span> * Load the Language class </span><span>219</span> <span> * ------------------------------------------------------ </span><span>220</span> <span>*/</span> <span>221</span> <span>$LANG</span> =& load_class('Lang', 'core'<span>); </span><span>222</span> <span>223</span> <span>/*</span> <span>224</span> <span> * ------------------------------------------------------ </span><span>225</span> <span> * Load the app controller and local controller </span><span>226</span> <span> * ------------------------------------------------------ </span><span>227</span> <span> * </span><span>228</span> <span>*/</span> <span>229</span> <span>//</span><span> Load the base controller class</span> <span>230</span> <span>require</span> BASEPATH.'core/Controller.php'<span>; </span><span>231</span> <span>232</span> <span>function</span> &<span>get_instance() </span><span>233</span> <span> { </span><span>234</span> <span>return</span> CI_Controller::<span>get_instance(); </span><span>235</span> <span> } </span><span>236</span> <span>237</span> <span>238</span> <span>if</span> (<span>file_exists</span>(APPPATH.'core/'.<span>$CFG</span>->config['subclass_prefix'].'Controller.php'<span>)) </span><span>239</span> <span> { </span><span>240</span> <span>require</span> APPPATH.'core/'.<span>$CFG</span>->config['subclass_prefix'].'Controller.php'<span>; </span><span>241</span> <span> } </span><span>242</span> <span>243</span> <span>//</span><span> Load the local application controller </span><span>244</span> <span> // Note: The Router class automatically validates the controller path using the router->_validate_request(). </span><span>245</span> <span> // If this include fails it means that the default controller in the Routes.php file is not resolving to something valid.</span> <span>246</span> <span>if</span> ( ! <span>file_exists</span>(APPPATH.'controllers/'.<span>$RTR</span>->fetch_directory().<span>$RTR</span>->fetch_class().'.php'<span>)) </span><span>247</span> <span> { </span><span>248</span> show_error('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.'<span>); </span><span>249</span> <span> } </span><span>250</span> <span>251</span> <span>include</span>(APPPATH.'controllers/'.<span>$RTR</span>->fetch_directory().<span>$RTR</span>->fetch_class().'.php'<span>); </span><span>252</span> <span>253</span> <span>//</span><span> Set a mark point for benchmarking</span> <span>254</span> <span>$BM</span>->mark('loading_time:_base_classes_end'<span>); </span><span>255</span> <span>256</span> <span>/*</span> <span>257</span> <span> * ------------------------------------------------------ </span><span>258</span> <span> * Security check </span><span>259</span> <span> * ------------------------------------------------------ </span><span>260</span> <span> * </span><span>261</span> <span> * None of the functions in the app controller or the </span><span>262</span> <span> * loader class can be called via the URI, nor can </span><span>263</span> <span> * controller functions that begin with an underscore </span><span>264</span> <span>*/</span> <span>265</span> <span>$class</span> = <span>$RTR</span>-><span>fetch_class(); </span><span>266</span> <span>$method</span> = <span>$RTR</span>-><span>fetch_method(); </span><span>267</span> <span>268</span> <span>if</span> ( ! <span>class_exists</span>(<span>$class</span><span>) </span><span>269</span> OR <span>strncmp</span>(<span>$method</span>, '_', 1) == 0 <span>270</span> OR <span>in_array</span>(<span>strtolower</span>(<span>$method</span>), <span>array_map</span>('strtolower', <span>get_class_methods</span>('CI_Controller'<span>))) </span><span>271</span> <span> ) </span><span>272</span> <span> { </span><span>273</span> <span>if</span> ( ! <span>empty</span>(<span>$RTR</span>->routes['404_override'<span>])) </span><span>274</span> <span> { </span><span>275</span> <span>$x</span> = <span>explode</span>('/', <span>$RTR</span>->routes['404_override'<span>]); </span><span>276</span> <span>$class</span> = <span>$x</span>[0<span>]; </span><span>277</span> <span>$method</span> = (<span>isset</span>(<span>$x</span>[1]) ? <span>$x</span>[1] : 'index'<span>); </span><span>278</span> <span>if</span> ( ! <span>class_exists</span>(<span>$class</span><span>)) </span><span>279</span> <span> { </span><span>280</span> <span>if</span> ( ! <span>file_exists</span>(APPPATH.'controllers/'.<span>$class</span>.'.php'<span>)) </span><span>281</span> <span> { </span><span>282</span> show_404("{<span>$class</span>}/{<span>$method</span>}"<span>); </span><span>283</span> <span> } </span><span>284</span> <span>285</span> <span>include_once</span>(APPPATH.'controllers/'.<span>$class</span>.'.php'<span>); </span><span>286</span> <span> } </span><span>287</span> <span> } </span><span>288</span> <span>else</span> <span>289</span> <span> { </span><span>290</span> show_404("{<span>$class</span>}/{<span>$method</span>}"<span>); </span><span>291</span> <span> } </span><span>292</span> <span> } </span><span>293</span> <span>294</span> <span>/*</span> <span>295</span> <span> * ------------------------------------------------------ </span><span>296</span> <span> * Is there a "pre_controller" hook? </span><span>297</span> <span> * ------------------------------------------------------ </span><span>298</span> <span>*/</span> <span>299</span> <span>$EXT</span>->_call_hook('pre_controller'<span>); </span><span>300</span> <span>301</span> <span>/*</span> <span>302</span> <span> * ------------------------------------------------------ </span><span>303</span> <span> * Instantiate the requested controller </span><span>304</span> <span> * ------------------------------------------------------ </span><span>305</span> <span>*/</span> <span>306</span> <span>//</span><span> Mark a start point so we can benchmark the controller</span> <span>307</span> <span>$BM</span>->mark('controller_execution_time_( '.<span>$class</span>.' / '.<span>$method</span>.' )_start'<span>); </span><span>308</span> <span>309</span> <span>$CI</span> = <span>new</span> <span>$class</span><span>(); </span><span>310</span> <span>311</span> <span>/*</span> <span>312</span> <span> * ------------------------------------------------------ </span><span>313</span> <span> * Is there a "post_controller_constructor" hook? </span><span>314</span> <span> * ------------------------------------------------------ </span><span>315</span> <span>*/</span> <span>316</span> <span>$EXT</span>->_call_hook('post_controller_constructor'<span>); </span><span>317</span> <span>318</span> <span>/*</span> <span>319</span> <span> * ------------------------------------------------------ </span><span>320</span> <span> * Call the requested method </span><span>321</span> <span> * ------------------------------------------------------ </span><span>322</span> <span>*/</span> <span>323</span> <span>//</span><span> Is there a "remap" function? If so, we call it instead</span> <span>324</span> <span>if</span> (<span>method_exists</span>(<span>$CI</span>, '_remap'<span>)) </span><span>325</span> <span> { </span><span>326</span> <span>$CI</span>->_remap(<span>$method</span>, <span>array_slice</span>(<span>$URI</span>->rsegments, 2<span>)); </span><span>327</span> <span> } </span><span>328</span> <span>else</span> <span>329</span> <span> { </span><span>330</span> <span>//</span><span> is_callable() returns TRUE on some versions of PHP 5 for private and protected </span><span>331</span> <span> // methods, so we'll use this workaround for consistent behavior</span> <span>332</span> <span>if</span> ( ! <span>in_array</span>(<span>strtolower</span>(<span>$method</span>), <span>array_map</span>('strtolower', <span>get_class_methods</span>(<span>$CI</span><span>)))) </span><span>333</span> <span> { </span><span>334</span> <span>//</span><span> Check and see if we are using a 404 override and use it.</span> <span>335</span> <span>if</span> ( ! <span>empty</span>(<span>$RTR</span>->routes['404_override'<span>])) </span><span>336</span> <span> { </span><span>337</span> <span>$x</span> = <span>explode</span>('/', <span>$RTR</span>->routes['404_override'<span>]); </span><span>338</span> <span>$class</span> = <span>$x</span>[0<span>]; </span><span>339</span> <span>$method</span> = (<span>isset</span>(<span>$x</span>[1]) ? <span>$x</span>[1] : 'index'<span>); </span><span>340</span> <span>if</span> ( ! <span>class_exists</span>(<span>$class</span><span>)) </span><span>341</span> <span> { </span><span>342</span> <span>if</span> ( ! <span>file_exists</span>(APPPATH.'controllers/'.<span>$class</span>.'.php'<span>)) </span><span>343</span> <span> { </span><span>344</span> show_404("{<span>$class</span>}/{<span>$method</span>}"<span>); </span><span>345</span> <span> } </span><span>346</span> <span>347</span> <span>include_once</span>(APPPATH.'controllers/'.<span>$class</span>.'.php'<span>); </span><span>348</span> <span>unset</span>(<span>$CI</span><span>); </span><span>349</span> <span>$CI</span> = <span>new</span> <span>$class</span><span>(); </span><span>350</span> <span> } </span><span>351</span> <span> } </span><span>352</span> <span>else</span> <span>353</span> <span> { </span><span>354</span> show_404("{<span>$class</span>}/{<span>$method</span>}"<span>); </span><span>355</span> <span> } </span><span>356</span> <span> } </span><span>357</span> <span>358</span> <span>//</span><span> Call the requested method. </span><span>359</span> <span> // Any URI segments present (besides the class/function) will be passed to the method for convenience</span> <span>360</span> <span>call_user_func_array</span>(<span>array</span>(&<span>$CI</span>, <span>$method</span>), <span>array_slice</span>(<span>$URI</span>->rsegments, 2<span>)); </span><span>361</span> <span> } </span><span>362</span> <span>363</span> <span>364</span> <span>//</span><span> Mark a benchmark end point</span> <span>365</span> <span>$BM</span>->mark('controller_execution_time_( '.<span>$class</span>.' / '.<span>$method</span>.' )_end'<span>); </span><span>366</span> <span>367</span> <span>/*</span> <span>368</span> <span> * ------------------------------------------------------ </span><span>369</span> <span> * Is there a "post_controller" hook? </span><span>370</span> <span> * ------------------------------------------------------ </span><span>371</span> <span>*/</span> <span>372</span> <span>$EXT</span>->_call_hook('post_controller'<span>); </span><span>373</span> <span>374</span> <span>/*</span> <span>375</span> <span> * ------------------------------------------------------ </span><span>376</span> <span> * Send the final rendered output to the browser </span><span>377</span> <span> * ------------------------------------------------------ </span><span>378</span> <span>*/</span> <span>379</span> <span>if</span> (<span>$EXT</span>->_call_hook('display_override') === <span>FALSE</span><span>) </span><span>380</span> <span> { </span><span>381</span> <span>$OUT</span>-><span>_display(); </span><span>382</span> <span> } </span><span>383</span> <span>384</span> <span>/*</span> <span>385</span> <span> * ------------------------------------------------------ </span><span>386</span> <span> * Is there a "post_system" hook? </span><span>387</span> <span> * ------------------------------------------------------ </span><span>388</span> <span>*/</span> <span>389</span> <span>$EXT</span>->_call_hook('post_system'<span>); </span><span>390</span> <span>391</span> <span>/*</span> <span>392</span> <span> * ------------------------------------------------------ </span><span>393</span> <span> * Close the DB connection if one exists </span><span>394</span> <span> * ------------------------------------------------------ </span><span>395</span> <span>*/</span> <span>396</span> <span>if</span> (<span>class_exists</span>('CI_DB') AND <span>isset</span>(<span>$CI</span>-><span>db)) </span><span>397</span> <span> { </span><span>398</span> <span>$CI</span>->db-><span>close(); </span><span>399</span> <span> } </span><span>400</span> <span>401</span> <span>402</span> <span>/*</span><span> End of file CodeIgniter.php </span><span>*/</span> <span>403</span> <span>/*</span><span> Location: ./system/core/CodeIgniter.php </span><span>*/</span>View Code
在CodeIgniter中,可以看到开头的英文描述,该脚本时系统初始化文件,主要作用是装载基类和执行请求。
31-45行:定义了CI_VERSION常量,描述当前框架版本,CI_CORE常量,目前我也不清楚没探究过,注释是CI的分支,啥意思?
52行:加载系统核心目录下的Common.php文件,Load the global functions,记得前一篇中说到,一般一个项目会将很多公共方法放在一个脚本中加载进来,通常取名Utilities.php,也可是Common.php,这里的Common.php也是这个意思,如它的解释是“加载全局函数”,即这里的函数都是后边直接拿来用的。在这个脚本中有两个重要的方法(目前来说)一个是get_config,单独拿出来如下
<span> 1</span> <?<span>php </span><span> 2</span> <span>/*</span><span>* </span><span> 3</span> <span>* Loads the main config.php file </span><span> 4</span> <span>* </span><span> 5</span> <span>* This function lets us grab the config file even if the Config class </span><span> 6</span> <span>* hasn't been instantiated yet </span><span> 7</span> <span>* </span><span> 8</span> <span>* @access private </span><span> 9</span> <span>* @return array </span><span>10</span> <span>*/</span> <span>11</span> <span>if</span> ( ! <span>function_exists</span>('get_config'<span>)) </span><span>12</span> <span>{ </span><span>13</span> <span>function</span> &get_config(<span>$replace</span> = <span>array</span><span>()) </span><span>14</span> <span> { </span><span>15</span> <span>static</span> <span>$_config</span><span>; </span><span>16</span> <span>17</span> <span>if</span> (<span>isset</span>(<span>$_config</span><span>)) </span><span>18</span> <span> { </span><span>19</span> <span>return</span> <span>$_config</span>[0<span>]; </span><span>20</span> <span> } </span><span>21</span> <span>22</span> <span>//</span><span> Is the config file in the environment folder?</span> <span>23</span> <span>if</span> ( ! <span>defined</span>('ENVIRONMENT') OR ! <span>file_exists</span>(<span>$file_path</span> = APPPATH.'config/'.ENVIRONMENT.'/config.php'<span>)) </span><span>24</span> <span> { </span><span>25</span> <span>$file_path</span> = APPPATH.'config/config.php'<span>; </span><span>26</span> <span> } </span><span>27</span> <span>28</span> <span>//</span><span> Fetch the config file</span> <span>29</span> <span>if</span> ( ! <span>file_exists</span>(<span>$file_path</span><span>)) </span><span>30</span> <span> { </span><span>31</span> <span>exit</span>('The configuration file does not exist.'<span>); </span><span>32</span> <span> } </span><span>33</span> <span>34</span> <span>require</span>(<span>$file_path</span><span>); </span><span>35</span> <span>36</span> <span>//</span><span> Does the $config array exist in the file?</span> <span>37</span> <span>if</span> ( ! <span>isset</span>(<span>$config</span>) OR ! <span>is_array</span>(<span>$config</span><span>)) </span><span>38</span> <span> { </span><span>39</span> <span>exit</span>('Your config file does not appear to be formatted correctly.'<span>); </span><span>40</span> <span> } </span><span>41</span> <span>42</span> <span>//</span><span> Are any values being dynamically replaced?</span> <span>43</span> <span>if</span> (<span>count</span>(<span>$replace</span>) > 0<span>) </span><span>44</span> <span> { </span><span>45</span> <span>foreach</span> (<span>$replace</span> <span>as</span> <span>$key</span> => <span>$val</span><span>) </span><span>46</span> <span> { </span><span>47</span> <span>if</span> (<span>isset</span>(<span>$config</span>[<span>$key</span><span>])) </span><span>48</span> <span> { </span><span>49</span> <span>$config</span>[<span>$key</span>] = <span>$val</span><span>; </span><span>50</span> <span> } </span><span>51</span> <span> } </span><span>52</span> <span> } </span><span>53</span> <span>54</span> <span>$_config</span>[0] =& <span>$config</span><span>; </span><span>55</span> <span>return</span> <span>$_config</span>[0<span>]; </span><span>56</span> <span> } </span><span>57</span> }View Code
注释说它加载主要的config.php文件,它使得我们能抓取到配置文件,即便配置类还未被实例化。在CI中,有专门的核心配置类CI_Config来加载配置信息,而这里的get_config方法也能获得主要配置信息,注意是主要配置信息,在application/config目录下有很多其他的配置信息文件(前面在自定义配置变量时也说过CI将配置信息分为了很多文件),其中有一个config.php文件就是get_config能获取到的,这个文件存放的就是基本信息,如果你还想获取其他的配置信息,貌似就要用配置类了。所以如果想添加节本配置信息就在这个里边。
如果是第一次调用get_config方法,先声明静态变量$_config,如果已定义则直接返回它的索引为0的子数组。然后查看APPPATH/config/ENVIRONMENT/config.php文件是否存在(前面打印已知ENVIRONMENT常量值,未改动就是development,原始的框架中没有这个目录,所以这里加载的是application/config/config.php(只加载了这一个,其他的配置文件没有),可以打开看看config.php中定义了一个$config数组,一些基本定义如基础链接、链接后缀、编码、语言、缓存、日志、钩子等等。如果传入一个关联数组,它会将键-值(临时)加入$_config中。总之,get_config方法主要得到的是config.php中定义的数组变量。
与get_config相关的config_item方法则是得到这个数组变量中的某一项。
另一个比较重要的方法是load_class:
<span> 1</span> <?<span>php </span><span> 2</span> <span>/*</span><span>* </span><span> 3</span> <span>* Class registry </span><span> 4</span> <span>* </span><span> 5</span> <span>* This function acts as a singleton. If the requested class does not </span><span> 6</span> <span>* exist it is instantiated and set to a static variable. If it has </span><span> 7</span> <span>* previously been instantiated the variable is returned. </span><span> 8</span> <span>* </span><span> 9</span> <span>* @access public </span><span>10</span> <span>* @param string the class name being requested </span><span>11</span> <span>* @param string the directory where the class should be found </span><span>12</span> <span>* @param string the class name prefix </span><span>13</span> <span>* @return object </span><span>14</span> <span>*/</span> <span>15</span> <span>if</span> ( ! <span>function_exists</span>('load_class'<span>)) </span><span>16</span> <span>{ </span><span>17</span> <span>function</span> &load_class(<span>$class</span>, <span>$directory</span> = 'libraries', <span>$prefix</span> = 'CI_'<span>) </span><span>18</span> <span> { </span><span>19</span> <span>static</span> <span>$_classes</span> = <span>array</span><span>(); </span><span>20</span> <span>21</span> <span>//</span><span> Does the class exist? If so, we're done...</span> <span>22</span> <span>if</span> (<span>isset</span>(<span>$_classes</span>[<span>$class</span><span>])) </span><span>23</span> <span> { </span><span>24</span> <span>return</span> <span>$_classes</span>[<span>$class</span><span>]; </span><span>25</span> <span> } </span><span>26</span> <span>27</span> <span>$name</span> = <span>FALSE</span><span>; </span><span>28</span> <span>29</span> <span>//</span><span> Look for the class first in the local application/libraries folder </span><span>30</span> <span> // then in the native system/libraries folder</span> <span>31</span> <span>foreach</span> (<span>array</span>(APPPATH, BASEPATH) <span>as</span> <span>$path</span><span>) </span><span>32</span> <span> { </span><span>33</span> <span>if</span> (<span>file_exists</span>(<span>$path</span>.<span>$directory</span>.'/'.<span>$class</span>.'.php'<span>)) </span><span>34</span> <span> { </span><span>35</span> <span>$name</span> = <span>$prefix</span>.<span>$class</span><span>; </span><span>36</span> <span>37</span> <span>if</span> (<span>class_exists</span>(<span>$name</span>) === <span>FALSE</span><span>) </span><span>38</span> <span> { </span><span>39</span> <span>require</span>(<span>$path</span>.<span>$directory</span>.'/'.<span>$class</span>.'.php'<span>); </span><span>40</span> <span> } </span><span>41</span> <span>42</span> <span>break</span><span>; </span><span>43</span> <span> } </span><span>44</span> <span> } </span><span>45</span> <span>46</span> <span>//</span><span> Is the request a class extension? If so we load it too</span> <span>47</span> <span>if</span> (<span>file_exists</span>(APPPATH.<span>$directory</span>.'/'.config_item('subclass_prefix').<span>$class</span>.'.php'<span>)) </span><span>48</span> <span> { </span><span>49</span> <span>$name</span> = config_item('subclass_prefix').<span>$class</span><span>; </span><span>50</span> <span>51</span> <span>if</span> (<span>class_exists</span>(<span>$name</span>) === <span>FALSE</span><span>) </span><span>52</span> <span> { </span><span>53</span> <span>require</span>(APPPATH.<span>$directory</span>.'/'.config_item('subclass_prefix').<span>$class</span>.'.php'<span>); </span><span>54</span> <span> } </span><span>55</span> <span> } </span><span>56</span> <span>57</span> <span>//</span><span> Did we find the class?</span> <span>58</span> <span>if</span> (<span>$name</span> === <span>FALSE</span><span>) </span><span>59</span> <span> { </span><span>60</span> <span>//</span><span> Note: We use exit() rather then show_error() in order to avoid a </span><span>61</span> <span> // self-referencing loop with the Excptions class</span> <span>62</span> <span>exit</span>('Unable to locate the specified class: '.<span>$class</span>.'.php'<span>); </span><span>63</span> <span> } </span><span>64</span> <span>65</span> <span>//</span><span> Keep track of what we just loaded</span> <span>66</span> is_loaded(<span>$class</span><span>); </span><span>67</span> <span>68</span> <span>$_classes</span>[<span>$class</span>] = <span>new</span> <span>$name</span><span>(); </span><span>69</span> <span>return</span> <span>$_classes</span>[<span>$class</span><span>]; </span><span>70</span> <span> } </span><span>71</span> }View Code
先看它的注释:这个方法作为一个单例,如果被请求的类没有出现过,则该类会被实例化为一个static variable,如果先前被实例化过则直接返回它。它的三个参数分别是请求的类名、所在目录,类名前缀。可以看到,目录默认是libraries,在application和system中均有它,它就是存放我们自定义的类库或者CI自带的类库的地方,就是自定义工具和CI提供的工具,如日历类、加密类、Ftp类、日志类、Session会话类、Email邮件收发类、JavaScript类、ZIP压缩类等等。或许你已经注意到这里返回的是引用而非值,就像它将加载的类作为静态变量一样,这些细节地方最终提高了整个系统的访问速度。
大致流程:先定義一個靜態數組,若數組中已有該類別直接回傳。先後掃描APPPATH和BASEPATH(前面已知這兩個常數值)資料夾下的$directory(預設值是libraries)目錄下的$class.php檔案是否存在,存在則加上CI的標準類別前綴CI_(第三個參數的預設值),在檢查類別存在與否,存在則require該檔案(從這裡可知,class_exists()在判斷類別是否存在時並不需要先載入該類別檔案),一旦檔案出現則載入它,並break跳出。注意掃描順序,先APPPATH後BASEPATH,假如只傳第一個參數類名,則優先在我們自己開發的application目錄libraries中尋找,然後才去system目錄的libraries下邊。
由於我們可以將CI的核心類別擴展(繼承它們),所以在掃描APPPATH和BASEPATH的核心類別(名稱以CI_為前綴)目錄後,還要掃描APPPATH的libraries下邊是否有自訂的擴充類別(預設以MY_為前綴),有的話也要載入它們,然後實例化一個對應物件(有擴充類別是擴充類別)存入$_classes靜態陣列並傳回該物件。
對Common.php有大致了解後回到CodeIgniter.php腳本。
54-66行:載入APPPATH.'config/constants.php'腳本,constants.php如同名字一樣放的是framework constants,集中定義了一些常數,所以我們在加入常數時就可以放到這裡邊來定義。
68-78行:首先定義了一個自訂錯誤處理方法_exception_handler。判斷php版本,非5.3關閉magic_quotes引用,這個配置在5.3版本已棄用,提高安全性。
80-99行:這裡就是將前面說過的$assign_to_config自訂設定資訊數組暫時加到$_config數組中,透過get_config方法實現,前面說過$assign_to_config預設是沒有定義的,這裡的if語句也不會運行。
101-109行:設定自訂腳本最大執行時間為300秒(略長,跑日誌的話得更長)
111-118行:載入核心類別Benchmark,設定兩個標記點。 Benchmark基準測試類,就是測試某個開始標記到結束標記之間佔用的內存大小、執行時間等信息,測試嘛,當然它要結合CI中一個叫分析器的東西使用。
120-132行:載入核心類別Hooks,鉤子,設定了一個系統開始執行的鉤子(實際上未執行,因為application/config/config.php關於它的設定資訊預設為false,即不啟用鉤子)。它就相當於一個觸發器,在某個東西要執行前開始執行某些程式碼,例如控制器載入前、載入後等,一旦控制器載入就執行指定的程式碼。在這裡,它嘗試呼叫一個pre_system(系統執行前)的擴展,預設不執行。
134-145行:加載核心類Config,配置類,它用來加載其他需需要的配置信息,並且它再次加載$assign_to_config數組中配置信息如果該數組定義了的話。
147-159行:載入核心類別Utf8,編碼類別。
161-166行:載入核心類別URI,路由。
168-180行:載入核心類Router,路徑處理類,_set_routing方法設定好存取路徑。如果路徑配置數組$routing(前面提到預設是註解掉的)定義了的話,將覆蓋預設的路由配置。如果你輸入了不存在的腳本路徑,在這一步就停住,開始報404了,當然還得Router裡邊的方法處理。
Router類別裡面,URI作為它的一個成員存在,實際處理方法在URI類中,熟悉點的都知道CI的訪問方式默認是段(segment)的形式,據說更有利於搜尋引擎。一個簡單的存取方式是這樣的localhost/ci/index.php/Controller/Function/Arguments,它們將訪問的形式解析為需要的控制器,調用的方法,以及提供的參數列表,當然也可啟用傳統的查詢字串形式。具體方法略複雜。
187行:載入核心類別Output。
189-200行:透過Hooks類別和Output類別偵測有無緩存,有的話直接輸出快取頁面,跳出腳本了。這也是在CI的介紹中應用程式流程圖部分,當路徑處理完後,若有快取直接輸出的原因。
207行:載入核心類別Security。
214行:載入核心類別Input。
221行:載入核心類別Lang,語言處理。
229-235行:載入核心類別Controller,它是所有控制器的基類,而get_instance全域方法也能得到它的實例,Controller的牛逼之處在於,它將前面所有透過load_calss載入的libraries(預設)目錄(APPPATH和BASEPATH)中的工具庫全部實例化為對象,並作為它的屬性成員。所以這裡的get_instance方法得到的實例也被CI稱為超物件(好像是這個名字),因為透過這個物件就可以取得所有透過前面載入的物件實例。
238-242行:載入自訂的,對上一步的核心類別CI_Controller的擴充類別的文件,預設就是MY_Controller,當然前提是如果你擴充了的的話。
243-251行:透過核心類別Router的實例,擷取目前存取的控制器所在的目錄和類別名,不存在則報錯,存在則載入它,這裡就載入了預設的welcome控制器檔案。當然如果你自己定義了控制器類別檔案並訪問,也是在這裡被include進來的(透過Router類別提取子目錄$RTR->fetch_directory(),若存在,提取類別名稱$RTR->fetch_class()來找),大概在246行的if語句塊,就是檢查這個類別檔案是否存在。
252行:設定一個基準測試結束標記,標記載入基本核心類別結束(這些測試預設不會執行)。
256-292行:安全檢查。先透過Router類別取得類別名稱和要執行的方法名,if條件檢查3項內容。 1. 上面的243-251行是找到了控制器對應的腳本,並且加載了它,但是假如這只是一個名字匹配的空腳本呢?裡邊什麼都沒寫就不行了,於是要檢查類別的定義是否存在(class_exists),2. 以下劃線_開頭的方法名稱不能執行,直接報錯,當然這是CI自己的規則,也就是說無論你的類別定義的以_開頭的方法即使是公有存取屬性也不行(除了一個_remap),3. 當類別中的方法根控制器核心類別中的方法同名時也不行。定義方法名時有個印象就行了。進入if中就很可能會404了。
298行:Hooks類別嘗試呼叫一個pre_controller(控制器執行前)的擴展,預設沒有。
301-309行:基準測試類設定一個起點標記,目的在於測試控制器執行的時長(預設不顯示測試資訊),並且實例化前面載入的控制器類,預設的就是Welcome。
315行:Hooks嘗試執行post_controller_constructor(所呼叫的控制器類別建構完成後)的擴展,預設沒有。
317-364行:開始呼叫指定的控制器類別的指定方法(當然這裡是預設控制器Welcome的預設方法index)。看看這個流程,首先一個if判斷,如果你的控制器類別中有方法_remap,只呼叫它了,所以前面說以下劃線開頭的方法除了_remap,這也是CI的一個類別的方法的規則,有了這個重映射方法,只調它。預設的Welcome