在 程序入口处,index.php 用一句 Yii::createWebApplication($config)->run(); 开始了app的运行。
那么,首先查看 CWebApplication 的 构造函数,如下:
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']));
Yii::setPathOfAlias('ext',$this->getBasePath().DIRECTORY_SEPARATOR.'extensions');
$this->preinit();
$this->initSystemHandlers();
$this->registerCoreComponents();
$this->configure($config);
$this->attachBehaviors($this->behaviors);
$this->preloadComponents();
$this->init();
}
再来看下,run()函数的流程:
public function run()
{
if($this->hasEventHandler('onBeginRequest'))
$this->onBeginRequest(new CEvent($this));
register_shutdown_function(array($this,'end'),0,false);
$this->processRequest();
if($this->hasEventHandler('onEndRequest'))
$this->onEndRequest(new CEvent($this));
}
最后看框架是如何处理请求的:
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());
$this->runController($route);
}
由此可知,在 框架中的配置文件中,指定的 preload 组件,会在处理请求和路由分析之前执行,那么通过preload机制,我们能做的事就很多了,
比如:
想动态加载一些路由测略时,就可以自定义组件,先行于 processRequest进程,在自己的组件里 $this->getUrlManager()->addRules()。
值得一提的是,Yii里的组件是单例模式,先判断有没有已经存在,再去实例化组件,这使得在各个地方调用的组件延续性很好。