首页 >后端开发 >php教程 >CI加载流程小结

CI加载流程小结

WBOY
WBOY原创
2016-08-08 09:28:291050浏览

  无聊,决定水一把。

  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>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

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn