转载请注明:TheViperhttp://www.cnblogs.com/TheViper/
上一篇主要分析了Yii::createWebapplication ( $config )->run ();的createWebApplication ( $config )部分,这篇分析后面的。
run()也是不在CWebApplication里面,在CApplication 里。
1 <?php 2 abstract class CApplication extends CModule { 3 PRivate $_id; 4 private $_basePath; 5 abstract public function processRequest(); 6 public function __construct($config = null) { 7 if (is_string ( $config )) 8 $config = require ($config); 9 Yii::setApplication ( $this );//保存整个app实例10 if (isset ( $config ['basePath'] )) {11 $this->setBasePath ( $config ['basePath'] );12 unset ( $config ['basePath'] );13 } else14 $this->setBasePath ( 'protected' );15 //设置别名,后面就可以用application表示basePath了16 Yii::setPathOfAlias ( 'application', $this->getBasePath () );17 //钩子,模块 预 初始化时执行,子类实现。不过这时,配置还没有写入框架18 $this->preinit ();19 $this->registerCoreComponents ();20 //父类实现21 $this->configure ( $config );22 //加载静态应用组件23 $this->preloadComponents ();24 //这才开始初始化模块25 $this->init ();26 }27 protected function registerCoreComponents() {28 $components = array (29 'request' => array (30 'class' => 'CHttpRequest'31 ),32 'urlManager' => array (33 'class' => 'CUrlManager'34 )35 );36 37 $this->setComponents ( $components );//父类实现38 }39 public function run() {40 $this->processRequest ();41 }42 public function getId() {43 if ($this->_id !== null)44 return $this->_id;45 else46 return $this->_id = sprintf ( '%x', crc32 ( $this->getBasePath () . $this->name ) );47 }48 public function setId($id) {49 $this->_id = $id;50 }51 public function getBasePath() {52 return $this->_basePath;53 }54 public function setBasePath($path) {55 if (($this->_basePath = realpath ( $path )) === false || ! is_dir ( $this->_basePath ))56 return;57 }58 public function getDb() {59 return $this->getComponent ( 'db' );//父类实现60 }61 public function getUrlManager() {62 return $this->getComponent ( 'urlManager' );63 }64 public function getController() {65 return null;66 }67 public function getBaseUrl($absolute = false) {68 return $this->getRequest ()->getBaseUrl ( $absolute );69 }70 }
run()又用了CWebApplication里面的processRequest()。薛强大哥(yii作者),架构要不要这样啊.裁剪后当然觉得这样的调用很没意思。
后面的主要在CWebApplication里了。
1 <?php 2 class CWebApplication extends CApplication { 3 public $controllerNamespace; 4 private $_controllerPath; 5 private $_viewPath; 6 private $_systemViewPath; 7 private $_controller; 8 public $controllerMap=array(); 9 public function processRequest() {//开始执行请求10 //获取urlManager组件,解析请求,得到controller/action这种格式的string,11 //并且将隐藏参数与请求的参数一一对应,匹配起来,写入$_REQUEST中12 $route = $this->getUrlManager ()->parseUrl ($this->getRequest());13 $this->runController ( $route );14 }15 public function getRequest() {//获取request组件16 return $this->getComponent ( 'request' );17 }18 protected function registerCoreComponents() {//注册核心组件19 parent::registerCoreComponents ();20 }21 //执行contronller22 public function runController($route) {23 if (($ca = $this->createController ( $route )) !== null) {24 list ( $controller, $actionID ) = $ca;25 $oldController = $this->_controller;26 $this->_controller = $controller;27 $controller->init ();//钩子,在执行action方法前调用,子类去实现28 $controller->run ( $actionID );//开始转入controller类中action方法的执行29 $this->_controller = $oldController;30 }31 }32 //创建controller类实例,从controller/action这种格式的string中解析出$controller, $actionID 33 public function createController($route, $owner = null) {34 if ($owner === null)35 $owner = $this;36 if (($route = trim ( $route, '/' )) === '')37 $route = $owner->defaultController;38 39 $route .= '/';40 while ( ($pos = strpos ( $route, '/' )) !== false ) {41 $id = substr ( $route, 0, $pos );42 if (! preg_match ( '/^\w+$/', $id ))43 return null;44 $id = strtolower ( $id );45 $route = ( string ) substr ( $route, $pos + 1 );46 if (! isset ( $basePath )) // first segment47 {48 $basePath = $owner->getControllerPath ();49 $controllerID = '';50 } else {51 $controllerID .= '/';52 }53 $className = ucfirst ( $id ) . 'Controller';54 $classFile = $basePath . DIRECTORY_SEPARATOR . $className . '.php';55 56 if (is_file ( $classFile )) {57 if (! class_exists ( $className, false ))58 require ($classFile);59 if (class_exists ( $className, false ) && is_subclass_of ( $className, 'CController' )) {60 $id [0] = strtolower ( $id [0] );61 return array (62 new $className ( $controllerID . $id, $owner === $this ? null : $owner ),63 $this->parseActionParams ( $route )64 );65 }66 return null;67 }68 $controllerID .= $id;69 $basePath .= DIRECTORY_SEPARATOR . $id;70 }71 }72 protected function parseActionParams($pathInfo) {73 if (($pos = strpos ( $pathInfo, '/' )) !== false) {74 $manager = $this->getUrlManager ();//再次获取urlManager,在上面第一次调用中已经导入。75 $manager->parsePathInfo ( ( string ) substr ( $pathInfo, $pos + 1 ) );76 $actionID = substr ( $pathInfo, 0, $pos );77 return $manager->caseSensitive ? $actionID : strtolower ( $actionID );78 } else79 return $pathInfo;80 }81 public function getControllerPath() {82 if ($this->_controllerPath !== null)83 return $this->_controllerPath;84 else85 return $this->_controllerPath = $this->getBasePath () . DIRECTORY_SEPARATOR . 'controllers';86 }87 //两个钩子,子类去实现88 public function beforeControllerAction($controller, $action) {89 return true;90 }91 public function afterControllerAction($controller, $action) {92 }93 protected function init() {94 parent::init ();95 }96 }
对于$this->getUrlManager (),YiiBase里面有'CUrlManager' => 'CUrlManager.php'这个映射,说明是实例化了CUrlManager这个类。
1 <?php 2 class CUrlManager { 3 const GET_FORMAT = 'get'; 4 public $rules = array (); 5 public $urlSuffix = ''; 6 public $caseSensitive = true; 7 public $urlRuleClass = 'CUrlRule'; 8 private $_urlFormat = self::GET_FORMAT; 9 private $_rules = array ();10 private $_baseUrl;11 protected function processRules() {12 //遍历自定义的请求匹配规则13 foreach ( $this->rules as $pattern => $route ) {14 //对每一个规则创建CUrlRule实例15 $this->_rules [] = $this->createUrlRule ( $route, $pattern );16 }17 }18 protected function createUrlRule($route, $pattern) {19 if (is_array ( $route ) && isset ( $route ['class'] ))20 return $route;21 else {22 //import第二个参数表示是否立即包含类文件。 如果为flase,则类文件仅在被使用时包含。 这个参数仅当使用一个类的路径 别名 时才会用到23 $urlRuleClass = Yii::import ( $this->urlRuleClass, true );24 //创建CUrlRule实例25 return new $urlRuleClass ( $route, $pattern );26 }27 }28 //类似于__construct()29 public function init() {30 $this->processRules ();31 }32 public fu