程序执行流程跟踪:
1 index.php
Yii::createWebApplication($config)->run(); //step 1 tracestep
2 yii/framework/yiibase.php
public static function createApplication($class,$config=null)
{
return new $class($config);//$class="CWebApplication";
}
3 yii/framework/web/CWebApplication.php
class CWebApplication extends CApplication
真正执行的是类CApplication的构造函数
yii/framework/base/CApplication.php
public function __construct($config=null)
{
//phptest($config);
Yii::setApplication($this); //设置当前程序实例给Yii类,方便通过Yii::app()应用
// set basePath at early as possible to avoid trouble
if(is_string($config))
$config=require($config);//得到配置参数,以数组形式返回给$config;
if(isset($config['basePath']))
{
//var_dump(realpath($config['basePath']));
$this->setBasePath($config['basePath']); 设置路径
unset($config['basePath']); //unset $config中的basePath;
}
else
$this->setBasePath('protected');
Yii::setPathOfAlias('application',$this->getBasePath());
Yii::setPathOfAlias('webroot',dirname($_SERVER['SCRIPT_FILENAME'])); 当前运行的程序的路径
Yii::setPathOfAlias('ext',$this->getBasePath().DIRECTORY_SEPARATOR.'extensions');//设置程序拓展路径
//var_dump(dirname($_SERVER['SCRIPT_FILENAME']));
$this->preinit();
$this->initSystemHandlers();
$this->registerCoreComponents();
$this->configure($config);将当前配置参数执行成类得属性
$this->attachBehaviors($this->behaviors);
$this->preloadComponents();
$this->init();
}
4 执行run()函数
public function run()
{
//debug_print_backtrace();//step 2 tracestep
//echo "zj";//
if($this->hasEventHandler('onBeginRequest'))
$this->onBeginRequest(new CEvent($this));
$this->processRequest(); //到CWebApplication.php 111 处理程序请求
if($this->hasEventHandler('onEndRequest'))
$this->onEndRequest(new CEvent($this));
}
5 yii/framework/web/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());
//debug_print_backtrace();
$this->runController($route); //step 3 tracestep
}
6 yii/framework/web/CWebApplication.php
public function runController($route)
{
if(($ca=$this->createController($route))!==null)
{
//debug_print_backtrace();
list($controller,$actionID)=$ca;
$oldController=$this->_controller;
$this->_controller=$controller;
$controller->init();
$controller->run($actionID); //step 4 tracestep 到framework/web/filters/cfilterchain.php 124
$this->_controller=$oldController;
}
else
throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
array('{route}'=>$route===''?$this->defaultController:$route)));
}
7 上面的$controller->run($actionID)
真正执行的是yii/framework/web/CController.php的run
public function run($actionID)
{
//echo "zhoujian2";
if(($action=$this->createAction($actionID))!==null)
{
if(($parent=$this->getModule())===null)
$parent=Yii::app();
if($parent->beforeControllerAction($this,$action))
{
//debug_print_backtrace();
$this->runActionWithFilters($action,$this->filters());
$parent->afterControllerAction($this,$action);
}
}
else
$this->missingAction($actionID);
}
8 然后上面中的$this->runActionWithFilters($action,$this->filters());
在yii/framework/web/CController.php
public function runActionWithFilters($action,$filters)
{
if(empty($filters))
$this->runAction($action);//为空的话直接执行action
else
{
//debug_print_backtrace();
$priorAction=$this->_action;
$this->_action=$action;
CFilterChain::create($this,$action,$filters)->run();
$this->_action=$priorAction;
}
}
9 上面的CFilterChain::create($this,$action,$filters)->run();
在yii/framework/web/filters/CFilterChain.php
create函数里面首先穿件一个CFilterChain类得实例,然后处理并且,返回这个实例对象
然后调用刚才得到的CFilterChain对象的run方法
public function run()
{
if($this->offsetExists($this->filterIndex))
{
//debug_print_backtrace();
$filter=$this->itemAt($this->filterIndex++);
Yii::trace('Running filter '.($filter instanceof CInlineFilter ?
get_class($this->controller).'.filter'.$filter->name.'()':get_class($filter).'.filter()'),'system.web.filters.CFilterChain');
$filter->filter($this);//step 5 tracestep 到framework/web/filters/cinlinefilter.php 56
}
else
{
//debug_print_backtrace();
$this->controller->runAction($this->action); //step 9 tracestep 到framework/web/ccontroller.php 296
}
}
上面的大概意思如果有过滤就先过滤再执行controller->runAction();否则直接执行$this->runAction($action);//为空的话直接执行action
10
在yii/framework/web/CController.php
public function runAction($action)
{
//debug_print_backtrace();
$priorAction=$this->_action;
$this->_action=$action;
if($this->beforeAction($action))
{
if($action->runWithParams($this->getActionParams())===false)
//step 10 tracestep 到framework/web/actions/cinlineaction.php 42
$this->invalidActionParams($action);
else
$this->afterAction($action);
}
$this->_action=$priorAction;
}
11 上面的$action->runWithParams()
class CInlineAction extends CAction
yii/framework/web/actions/CInlineAction.php
public function runWithParams($params)
{
//debug_print_backtrace();
$methodName='action'.$this->getId();
$controller=$this->getController();
$method=new ReflectionMethod($controller, $methodName);
if($method->getNumberOfParameters()>0)
return $this->runWithParamsInternal($controller, $method, $params);
else
{
// phptest($methodName);
//step 11 tracestep 到framework/web/actions/cinlineaction.php 42
return $controller->$methodName();
//最终执行control中的方法(对应页面程序)/protect/controllers/SiteController.php的控制器和动作
}
}
过滤器:
在CController::run方法中
$this->runActionWithFilters($action,$this->filters());// 这里执行过滤器
比如在PostController中会存在
public function filters()
{
return array(
'accessControl', // perform access control for CRUD operations
);
}
注意这个函数有多态形式,
如果没有实现,会查找父类。
在siteController中就会继承CCtontroller::filters()
运行动作
capplication::run() ==> cwebapplication::processRequest() =>runcontroller($route)=>createController($route)返回control对象和action字符串;
controller=>run($actionID);
通过controller::createAction($actionID)得到$action
controller::runActionWithFilters($action,this->filters())
controller::runAction($action)
$action::runwithparams()
这里也有多态 一种是定义在cAction中,一种是cinlineAction