Yii 快速学习教程------抽丝剥茧(一) [转]
接触Yii也有一段时间了, 但是仍然对其中的不少东西不甚清楚,于是决定重新开始,并记录下自己的认识和体会.
抽丝剥茧------了解Yii 在一次请求中完成的具体过程.
1. index.php
Yii::createWebApplication($config)->run();
2. 于是看yii.php 发现Yii 继承自YiiBase,于是可知,其实执行了如下语句:
YiiBase::createWebApplication($config)->run();
3. 进入YiiBase.php
public static function createWebApplication($config=null)
{
return self::createApplication('CWebApplication',$config);
}
4. 于是进入CWebApplication.php, 发现没构造函数且继承自CApplication,再进入CApplication.php
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']));//设置webroot的根路径别名.
Yii::setPathOfAlias('ext',$this->getBasePath().DIRECTORY_SEPARATOR.'extensions');//设置extension的根路径别名.
$this->preinit();
$this->initSystemHandlers(); //初始化异常处理机制
$this->registerCoreComponents();//注册核心组件
//继承关系
$this->configure($config); //CModule中定义,
$this->attachBehaviors($this->behaviors); //在CComponent中定义, 为实例添加行为.
$this->preloadComponents();//加载config文件main.php 中的preload 项
$this->init();//加载处理request请求的组件CHttpRequest.于是可触发onBeginRequest 事件.
}
5.一切就绪之后, 运行实际上是CApplication的run函数,处理就此展开了.
public function run()
{
if($this->hasEventHandler('onBeginRequest'))
$this->onBeginRequest(new CEvent($this));
$this->processRequest();
if($this->hasEventHandler('onEndRequest'))
$this->onEndRequest(new CEvent($this));
}
6.于是查看CWebApplication.php
public function processRequest()
{
if(is_array($this->catchAllRequest) && isset($this->catchAllRequest[0]))
{
$route=$this->catchAllRequest[0];
foreach(array_splice($this->catchAllRequest,1) as $name=>$value)
$_GET[$name]=$value;
}
else
$route=$this->getUrlManager()->parseUrl($this->getRequest());//解析URL
$this->runController($route);//运行Controller
}
public function runController($route)
{
if(($ca=$this->createController($route))!==null) //创建Controller
{
list($controller,$actionID)=$ca;
$oldController=$this->_controller;
$this->_controller=$controller;
$controller->init();
$controller->run($actionID);
$this->_controller=$oldController;
}
else
throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
array('{route}'=>$route===''?$this->defaultController:$route)));
}
//createController太长因此没有贴出来,功能无非是从$route解析出controller 和action, 查找文件,如果存在, 创建controller实例.
7.因为所有Controller都继承自CCtroller,所以$controller->run($actionID)实际上是CController的方法,于是进入CController.php
public function run($actionID)
{
if(($action=$this->createAction($actionID))!==null)
{
if(($parent=$this->getModule())===null)
$parent=Yii::app();
if($parent->beforeControllerAction($this,$action))//CWebApplication中定义默认返回为true.即执行前,进行过滤
{
$this->runActionWithFilters($action,$this->filters());
$parent->afterControllerAction($this,$action);//CWebApplication中定义
}
}
else
$this->missingAction($actionID);//没有action错误.
}
public function runActionWithFilters($action,$filters)
{
if(empty($filters))//是否有过滤条件,没有就直接执行, 有则进行权限过滤
$this->runAction($action);
else
{
$priorAction=$this->_action;
$this->_action=$action;
CFilterChain::create($this,$action,$filters)->run();
$this->_action=$priorAction;
}
}
public function runAction($action)
{
$priorAction=$this->_action;
$this->_action=$action;
if($this->beforeAction($action))
{
if($action->runWithParams($this->getActionParams())===false)
$this->invalidActionParams($action);
else
$this->afterAction($action);
}
$this->_action=$priorAction;
}
8.再一次进入CInlineAction.php
public function runWithParams($params)
{
$methodName='action'.$this->getId();
$controller=$this->getController();
$method=new ReflectionMethod($controller, $methodName);
if($method->getNumberOfParameters()>0)
return $this->runWithParamsInternal($controller, $method, $params);
else
return$controller->$methodName();
}
好了,就此打住.来整理一下思绪, 不然脑子真有点乱.
1. 浏览器发送了一个请求, 有代理服务器重定向到index.php, 这里include yii文件和配置文件webroot/config/main.php.并执行.
Yii::createWebApplication($config)->run();
2.由于createWebApplication实际上是Yii继承自父类YiiBase的,所以执行
YiiBase::createWebApplication($config)->run();
3. 创建CWebApplication时, 会先执行其父类CApplication的构造函数, 在构造函数中完成了一下重要的步骤:
4. 创建对象完成后,再运行run函数,启动处理过程.