近日对Yii的请求处理有些疑惑~所以便开始了对Yii的源码的研究.
这是官方的一副流程图.
打开源码~开始了请求的追踪.
当一次请求被处理的时候~程序先调用了project/index.php文件,里面有如下几行代码:
1 2 3 4 5 6 7 8 9 |
// change the following paths if necessary $yii=dirname(__FILE__).'/../yii/framework/yii.php'; $config=dirname(__FILE__).'/protected/config/main.php'; // remove the following line when in production mode defined('YII_DEBUG') or define('YII_DEBUG',true); require_once($yii); Yii::createWebApplication($config)->run(); |
这段代码首先讲yii.php文件和main.php文件放入2个变量中,然后设置了YII_DEBUG变量为true,接着require_once了yii.php文件,并调用了run()方法.
yii.php文件有如下代码:
1 2 3 4 |
require(dirname(__FILE__).'/YiiBase.php'); class Yii extends YiiBase { } |
这段代码导入了yiibase.php,并定义了类Yii,该类继承YiiBase.
main.php里面是各种配置的信息,将配置信息作为数组返回.
Yii继承YiiBase,于是又找到YiiBase.php文件,发现这个文件开始的时候定义了如下几个变量:YII_BEGIN_TIME,YII_DEBUG,YII_ENABLE_EXCEPTION_HANDLER,YII_ENABLE_ERROR_HANDLER和YII_BATH.
找到createWebApplication方法,里面就一条语句:
1 |
return new CWebApplication($config); |
于是又找到yii/framework/web/CWebApplication.php文件,但是却没有在里面找到构造函数,由于该类继承CApplication,又找到yii/framework/base/CApplication.php,这个类里有构造函数,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public function __construct($config=null) { Yii::setApplication($this); // set basePath at early as possible to avoid trouble if(is_string($config)) $config=require($config); if(isset($config['basePath'])) { $this->setBasePath($config['basePath']); unset($config['basePath']); } else $this->setBasePath('protected'); Yii::setPathOfAlias('application',$this->getBasePath()); Yii::setPathOfAlias('webroot',dirname($_SERVER['SCRIPT_FILENAME'])); $this->preinit(); $this->initSystemHandlers(); $this->registerCoreComponents(); $this->configure($config); $this->attachBehaviors($this->behaviors); $this->preloadComponents(); $this->init(); } |
第一句Yii::setApplication($app);调用YiiBase里的setApplication()方法,该方法内容如下:
1 2 3 4 5 6 7 |
public static function setApplication($app) { if(self::$_app===null || $app===null) self::$_app=$app; else throw new CException(Yii::t('yii','Yii application can only be created once.')); } |
这个方法的目的是实例化一个app对象.
第6行到第14行设定了config和basePath.第15句和第16句设定了2个路径的快捷方式, webroot和application.
第18行调用了preinit()方法,该方法在该类中没有,是该类的父类CModule里的,但是找到yii/framework/base/CModule.php后,发现该方法内容为空.
第20行调用了initSystemHandlers,该方法位于该类中,内容如下:
1 2 3 4 5 6 7 |
protected function initSystemHandlers() { if(YII_ENABLE_EXCEPTION_HANDLER) set_exception_handler(array($this,'handleException')); if(YII_ENABLE_ERROR_HANDLER) set_error_handler(array($this,'handleError'),error_reporting()); } |
第21行调用了registerCoreComponents方法,该方法内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
protected function registerCoreComponents() { $components=array( 'coreMessages'=>array( 'class'=>'CPhpMessageSource', 'language'=>'en_us', 'basePath'=>YII_PATH.DIRECTORY_SEPARATOR.'messages', ), 'db'=>array( 'class'=>'CDbConnection', ), 'messages'=>array( 'class'=>'CPhpMessageSource', ), 'errorHandler'=>array( 'class'=>'CErrorHandler', ), 'securityManager'=>array( 'class'=>'CSecurityManager', ), 'statePersister'=>array( 'class'=>'CStatePersister', ), ); $this->setComponents($components); } |
第23行调用了configure方法,该方法在父类CModule里,内容如下:
1 2 3 4 5 6 7 8 |
public function configure($config) { if(is_array($config)) { foreach($config as $key=>$value) $this->$key=$value; } } |
第24行调用了attachBehaviors方法,该方法位于父类CModule的父类CComponent类中,内容如下:
1 2 3 4 5 |
public function attachBehaviors($behaviors) { foreach($behaviors as $name=>$behavior) $this->attachBehavior($name,$behavior); } |
第25行调用了preloadComponents方法,该方法同样位于父类CModule里,内容如下:
1 2 3 4 5 |
protected function preloadComponents() { foreach($this->preload as $id) $this->getComponent($id); } |
第27行调用了init方法,该方法位于父类CModule方法中,内容为空.
至此Yii::createWebApplication($config)方法已经分析完成~剩下的就是run()方法了.