yii       

yii架构分析

yii是由php编写的web后端框架

问题

1.请求url进入到yii的入口

2.如何解析url

3.MVC之间的接口

4.yii一直在监听的主程序

5.祖先类

6.结果怎么传给客户端

7.yii 事件机制

8.nginx yii参数传递

9.view 和layout关系

###分析

4.框架加载(when)

index.php

<?php

// change the following paths if necessary
$yii=dirname(__FILE__).'/../../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();

abstract class CApplication extends CModule

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']));
	if(isset($config['extensionPath']))
	{
		$this->setExtensionPath($config['extensionPath']);
		unset($config['extensionPath']);
	}
	else
		Yii::setPathOfAlias('ext',$this->getBasePath().DIRECTORY_SEPARATOR.'extensions');
	if(isset($config['aliases']))
	{
		$this->setAliases($config['aliases']);
		unset($config['aliases']);
	}

	$this->preinit();

	$this->initSystemHandlers();
	$this->registerCoreComponents();

	$this->configure($config);
	$this->attachBehaviors($this->behaviors);
	$this->preloadComponents();

	$this->init();
}

CModule.php

public function configure($config)
{
	if(is_array($config))
	{
		foreach($config as $key=>$value)
			$this->$key=$value;
	}
}

CWebApplication.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));

CComponent.php

public function raiseEvent($name,$event)
{
	$name=strtolower($name);
	if(isset($this->_e[$name]))
	{
		foreach($this->_e[$name] as $handler)
		{
			if(is_string($handler))
				call_user_func($handler,$event);
			elseif(is_callable($handler,true))
			{
				if(is_array($handler))
				{
					// an array: 0 - object, 1 - method name
					list($object,$method)=$handler;
					if(is_string($object))	// static method call
						call_user_func($handler,$event);
					elseif(method_exists($object,$method))
						$object->$method($event);
					else
						throw new CException(Yii::t('yii','Event "{class}.{event}" is attached with an invalid handler "{handler}".',
							array('{class}'=>get_class($this), '{event}'=>$name, '{handler}'=>$handler[1])));
				}
				else // PHP 5.3: anonymous function
					call_user_func($handler,$event);
			}
			else
				throw new CException(Yii::t('yii','Event "{class}.{event}" is attached with an invalid handler "{handler}".',
					array('{class}'=>get_class($this), '{event}'=>$name, '{handler}'=>gettype($handler))));
			// stop further handling if param.handled is set true
			if(($event instanceof CEvent) && $event->handled)
				return;
		}
	}
	elseif(YII_DEBUG && !$this->hasEvent($name))
		throw new CException(Yii::t('yii','Event "{class}.{event}" is not defined.',
			array('{class}'=>get_class($this), '{event}'=>$name)));
}

CWebApplication.php

	/**
 * Processes the current request.
 * It first resolves the request into controller and action,
 * and then creates the controller to perform the action.
 */
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);
}





public function runController($route)
{
	if(($ca=$this->createController($route))!==null)
	{
		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)));
}

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))
		{
			$this->runActionWithFilters($action,$this->filters());
			$parent->afterControllerAction($this,$action);
		}
	}
	else
		$this->missingAction($actionID);
}



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;
}

CAction.php

public function runWithParams($params)
{
	$method=new ReflectionMethod($this, 'run');
	if($method->getNumberOfParameters()>0)
		return $this->runWithParamsInternal($this, $method, $params);
	else
		return $this->run();
}


protected function runWithParamsInternal($object, $method, $params)
{
	$ps=array();
	foreach($method->getParameters() as $i=>$param)
	{
		$name=$param->getName();
		if(isset($params[$name]))
		{
			if($param->isArray())
				$ps[]=is_array($params[$name]) ? $params[$name] : array($params[$name]);
			elseif(!is_array($params[$name]))
				$ps[]=$params[$name];
			else
				return false;
		}
		elseif($param->isDefaultValueAvailable())
			$ps[]=$param->getDefaultValue();
		else
			return false;
	}
	$method->invokeArgs($object,$ps);
	return true;
}

CViewAction.php

public function run()
{
	$this->resolveView($this->getRequestedView());
	$controller=$this->getController();
	if($this->layout!==null)
	{
		$layout=$controller->layout;
		$controller->layout=$this->layout;
	}

	$this->onBeforeRender($event=new CEvent($this));
	if(!$event->handled)
	{
		if($this->renderAsText)
		{
			$text=file_get_contents($controller->getViewFile($this->view));
			$controller->renderText($text);
		}
		else
			$controller->render($this->view);
		$this->onAfterRender(new CEvent($this));
	}

	if($this->layout!==null)
		$controller->layout=$layout;
}

CController.php

public function renderText($text,$return=false)
{
	if(($layoutFile=$this->getLayoutFile($this->layout))!==false)
		$text=$this->renderFile($layoutFile,array('content'=>$text),true);

	$text=$this->processOutput($text);

	if($return)
		return $text;
	else
		echo $text;
}

public function render($view,$data=null,$return=false)
{
	if($this->beforeRender($view))
	{
		$output=$this->renderPartial($view,$data,true);
		if(($layoutFile=$this->getLayoutFile($this->layout))!==false)
			$output=$this->renderFile($layoutFile,array('content'=>$output),true);

		$this->afterRender($view,$output);

		$output=$this->processOutput($output);

		if($return)
			return $output;
		else
			echo $output;
	}
}

5.祖先类

CComponent

6.结果怎么传给客户端

php echo HTML 给web服务器,web服务器会打包成HTTP reponse给浏览器

###流程

请求url->解析url->controller->view

###模块