Yii请求处理流程分析

近日对Yii的请求处理有些疑惑~所以便开始了对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()方法了.

aliyun活动 https://www.aliyun.com/acts/limit-buy?userCode=re2o7acl
原文地址:https://www.cnblogs.com/wangbin/p/1521885.html